pythonのcodecsモジュールでrot13暗号の変換をした

ブログのネタが無さすぎて苦しんでいたが、ふと見るとペットボトルが目に留まった。今年のpyconjpでもらった水のペットボトルだ。

そして、外側のフィルムには妙な問題が書いてある。

super_difficult_encryption = '?????'

import codecs
print(
	codecs.decode(
		'FRAFL ybirf Clguba naq NV!',
		super_difficult_encryption
	)
)

そのままじゃ読めない暗号を解読してくれってことだろう。
俺がいた大学の数理情報工学では暗号理論も多少勉強するし、東大の五月祭の出展では暗号を題材にしたこともある。暗号の話は多少心得がある。
復号のための鍵もないから、これで戻すとなるとrot13あたりじゃねーか?

と思ってpythonのcodecモジュールを確認すると、rot13があったので、'?????'を'rot13'に変えて実行。

SENSY loves Python and AI!

よし。無事に暗号が解読できた。なおSENSYというのはPyCon JPのスポンサーで、この水を提供してくれた企業である。

rot13とは

アルファベットを13文字ずらす暗号である。(アルファベットは全部で26文字なので、もう一度この操作をすると元に戻る。)
暗号文'FRAFL ybirf Clguba naq NV!'の最初のFを復号すると、Fの13文字先にあるSになる。

codecsモジュールとは

codecsモジュールは暗号を作るためのモジュールなのかと思ったが、そうではなさそうだ。

7.2. codecs ? codec レジストリと基底クラス
このモジュールは、標準的な Python codec (エンコーダとデコーダ) 用の基底クラスを定義し、codec とエラー処理検索プロセスを管理する内部の Python codec レジストリへのアクセスを提供します。多くの codec はテキストをバイト形式にエンコードする テキストエンコーディング ですが、テキストをテキストに、またはバイトをバイトにエンコードする codec も提供されています。
7.2. codecs — codec レジストリと基底クラス — Python 3.6.5 ドキュメント

うーん。分かりにくい。初めての人がこれを読んでも分からないよ……

このページの方に各国のエンコーディングが載っていたので、文字エンコードの方式変換をするんだろう、きっと。

ただ、codecモジュールでできることは文字エンコードの変換に限らない。
例えばBase64エンコード/デコードも可能だ。
ただし入力はbytes-like objectに限られるので、文字列をそのまま入れることはできない。

import codecs

print(
	codecs.encode(
		b'Machine Learning', 'base64_codec'
	)
)

出力:
b'TWFjaGluZSBMZWFybmluZw==\n'


入力文字列の前のbを省くと
TypeError: encoding with 'base64_codec' codec failed (TypeError: expected bytes-like object, not str)
というエラーが出た。
base64_codecを使うときは、文字列(str)じゃなくて、bytes-like objectを入力してください」という意味である。

日々のアウトプットが変える!あなたのエンジニア・ライフ イベントレポート

2018年10月9日に開催されたこのイベントに参加してきました。 ※増枠【エンジニアのキャリアアップを語る】日々のアウトプットが変える!あなたのエンジニア・ライフ - connpass

まつもとりー(松本亮介)とKwappa(塩谷啓)さんのお二人による発表でした。 早速お二人の資料が上がっています。

資料を読めば分かることは適宜省いて、口頭で補足していたところを中心に書いています。資料と併せて読んでいただければと思います。

なぜポートフォリオが必要なのか - エンジニアと人事(評価・採用)両方向の視点から 松本亮介(まつもとりー)

なぜポートフォリオが必要なのか - エンジニアと人事(評価・採用)両方向の視点から - Speaker Deck

  1. はじめに
  2. 自分の体験
    • 6年前、28歳のとき…… 博士課程の1年目
    • OSS開発:Webではよくあるやり方
      • ビルドは通ってるけど「これ何に使うんだろう……」というあたりで公開していた
    • 博士課程に入って一番びっくりしたのは、オープンにできないことが多いこと
    • オープンに学術研究したいと思ったから大学院に入ったのに……!
    • でもオープンにやってみた
    • 批判を受けた
      • 論文ネタをオープンするなんて……!
      • 怒られたとしてもやりたいようにやっていこう
    • 指導教員の教授に相談してみた
      • 「松本さんが良いと思うやり方で好きなようにやってください。今のやり方、良いと思いますよ」
      • 迷いが消えた
    • ブログを書いても書いてもはてブ3とかしかつかない……
    • 徐々に広がり始める
      • 技術ってフェアというか平等なものなので、ネガティブなことを言われたら技術で見返そうと考えた。
      • 徐々に連鎖がつながっていって、少しずつ講演も依頼されるように
    • なんとなく自分の立ち位置が見えてくる
      • 強者の中で、みんなやってる中で自分も頑張ろう……と勉強を続けていると、どんどん成長してきた
      • 情熱が飛び火する 技術がただただ面白い
    • 頂上が見えてきた
      • 自分の得意分野、専門分野がどこか?
      • トップレベルの技術や人や企業はどこかが分かる
      • 自分を活かせる道が見えてくる
      • アウトプットというのは、自分のことを整理して外に出すこと
      • 脳内でふわっと曖昧だったものが、アウトプットすると明確化される
  3. 体験からポートフォリオの重要性を検討
    • エンジニア目線
      • 自身のスキルの明確化と再認識
        • 曖昧なままだと綺麗に整理理解できない。
        • アウトプットする中できちんと整理する
      • 周りを巻き込むことができる
        • アウトプット→スキルがつく→よりレベルの高いアウトプットができる
      • 先を予測できるようになる
        • アウトプットというものが、自分のスキルのストーリーのようなものになる
        • 自分のこの先目指す道、自分はこれが得意なんだ、などなど
    • 人事目線
      • スタンフォード助教とか取るときはまるまる3日間かけるらしい!
      • ちょっとの面接で採否を決めるのは本当に大変
      • アウトプットを永続的に残すことで、客観的な実力がわかる
    • アウトプットをまとめて、スキルのストーリーを作る

実践的アウトプット入門 塩谷啓(Kwappa)

実践的アウトプット入門 なぜ?なにを?どうやって? / Kwappa さん - ニコナレ 「日々のアウトプットが変える!あなたのエンジニア・ライフ」というイベントに登壇してきたよ #forkwell | Kwappa研究開発室

  • アウトプットとは?
  • なぜアウトプットするか?
    • データソースとして
      • 問題とその解決をコツコツログに書いて積み重ね
      • 学校の授業でノートに書くのって、後から見返す必要ないらしいですよ
    • 学びの定着と共有
      • 見せる前提で書くと理解が深まる
        • 人に見せられるようにしようと、綺麗なコード、より良い設計などを目指すから
      • 伝えることによって価値が増える
        • 誰か他のエンジニアの調べる時間を節約できる
    • コミュニケーションツールとして
      • 社内だと評価面談とか
      • 社外だと採用面接とか
  • 何をアウトプットするか?
    • 仕事メモ
      • データソースとして良い
      • 仕事中、何があって、何が困って、どうやって解決したかを書き留めたもの
      • 評価面談に使えるという面もあるけど
      • ネタ帳であるという面を意識しておく
    • 技術メモ
      • 上記の仕事メモの中から技術的な面を選り分ける、フィルターしたもの
      • 可搬性(社外に公開できるやつ)
        • 社外秘の部分を公開するわけにはいかないので 
      • 課外活動 趣味でアプリ作ってみたとか。
        • 「面白そうな技術があったので、触ってみた」でおしまいじゃなくて、困ったこと解決した方法を書いておけばネタ帳になる
    • プロダクト
  • どうやってアウトプットするか?
    • 自分用に書く
      • とにかく書く
      • ネタ帳、可搬性
      • メモツールにこだわってみよう Day Oneを使ってます
      • 「とにかく書く」といいながらも、再利用性も大事
        • 評価面談のネタにする
        • ネタ帳 などなど
    • 公開用に
      • ソースコードの場合はGitHub最強
      • 著書があると Amazonセントラルのページが作れる
        • フリーランスの人が住宅を購入するとき、融資の参考に使われたりするらしい……
      • こんな俺がこんな記事を書いてもつまらないんじゃ……って過度に萎縮しない。
        • 今の自分にできる、最高のアウトプットをし続けていればそれで良い
    • 人前でしゃべる

ポートフォリオレビュー

まずは、まつもとりーさんKwappaさんのポートフォリオを見た。その後、参加者の中から事前に選ばれた2人のポートフォリオのレビューの時間となった。

@ikedaosushi Forkwell Portfolio - エンジニア向けのポートフォリオサービス
@sachi21 Forkwell Portfolio - エンジニア向けのポートフォリオサービス

2人ともかなりの強者エンジニアで、すごいなーと思いながら見ていた。

質問:どういうことを書いたら自分の実績としてアピールできるだろうか?
書くことないなーと思ってたけど、毎日8時間仕事をやってれば何かしらあるわけで
 書き出す 自分の実績 日々やってきたこと中から紡ぎ出す

 OSSに関わる(自分でOSS製品を作る)という方法もあるよ
 OSSにするコツがだんだん出来てくる

質問:技術ブログ書いても反応がないから心が折れてきた
 Matzさんが「自分を踏み台にしてほしい」と言っていたことがあるけど
 自分のやっている分野で影響力ある人、影響力あるプロダクトとかに絡んでいく

(ikedaosushiさんに対してのコメント)
自分の強みをアピール出来ていて良い。
職歴を見ていると色々と面白そうなことをしてるのが分かる。その中に興味深いものがあって、もう少し知りたい、と思ったときに、その点の関連ブログ記事が(一般化されたとこで)ブログで書いてあったりするとさらに良い。

(sachi21さんに対してのコメント)
継続性 「いろいろやってるけどあんまり継続してないんじゃないか?」と思われがちなので、それに対して「GitHubで4年前から毎日草をはやしてます」と示せるのは素晴らしい。
手を動かすのに勝るものは無い

感想

雑感2点。

GitHubの共通言語っぷりがヤバい

最近、scounty、findy, そしてこのforkwell portfolioと、「どんなコードを書いてるか、GitHubリポジトリから分析しますね」というサービスがあまりに多い。
もはや「GitHub上にないコードは、あなたが書いたものではないと思え」という勢いだなと感じる……
(今更気づいたのかよ、とツッコまれそうだが)

ちゃんとGitHubに出すことを心がけよう。いきなり毎日やるとかは無理だけど。

課題をどう解決したか、を整理する

普段の業務でもプライベートの趣味の開発でも言えることだが。
「課題にぶつかって、いろいろ考えて解決しました」は誰しもやっていることである。
しかし大事なのはそれを明確に筋道立てて説明できること。
悲しいかな、この辺がしっかり説明できないと、「作業するとき何も考えてませんでした」に見えてしまう。
一旦整理してまとめたほうが良いな。

それでは。

機械学習モデルを解釈する方法 Permutation Importance / Partial Dependence Plot

Machine Learning for Insights Challengeで勉強した「Permutation Importance」と「Partial Dependence Plot」についてまとめる。

Machine Learning for Insights Challengeとは

9月18~21日に、kaggleの「Machine Learning for Insights Challenge」という講座が開催された。
1日に1通メールが来て、機械学習関連の話を学べる。
この記事では、4日のうち前半2日間の部分をまとめる。

なお、教材は公開されているので、今からでも同じように学習できる。
それぞれの日の説明には演習問題がついていて、kaggle kernel上で実行できる。

さてInsightsを日本語に直すと「洞察、物事の本質を見抜くこと」となるが、具体的には何なんだろうか。
「コースの始めに」に相当するUse Cases for Model Insights | Kaggleを見ると、このコースでは以下について学べると書いてある。

データのどの機能が最も重要であるとモデルは判断したか?
モデルからの単一の予測について、データ内のそれぞれの特徴量がその特定の予測にどのように影響したか?
全体的に見て、それぞれの特徴量はモデルの予測にどのような影響を与えるのか(多数の起こりうる予測を考慮した場合、典型的な効果は何か?)

以下の記事に出てくるような「解釈性(Interpretaility)」の話題と近いと考えておけば良さそうだ。
【記事更新】私のブックマーク「機械学習における解釈性(Interpretability in Machine Learning)」 - 人工知能学会 (The Japanese Society for Artificial Intelligence)

Permutation Importance

資料はこちら。下の方のリンクから演習問題に行ける。
Permutation Importance | Kaggle

機械学習のモデルを構築したときに「どの特徴量が重要なのか(feature importance)」を知る方法の一つが「Permutation Importance」である。

  1. モデルの訓練をする
  2. 1つの列の値をシャッフルして、その結果のデータセットを使用して予測を行う。 これらの予測値と真の目標値を使用して、シャッフルすることで損失関数がどれだけ悪くなったかを計算する。 そのパフォーマンス低下は、あなたが今シャッフルした変数の重要性を測定している。
  3. データを元の順序に戻す(手順2のシャッフルを元に戻す)。データセットのそれぞれの列で手順2を繰り返して、各列の重要度を計算する。

演習問題では「タクシーの料金」の予測をしていた。
乗車地点の緯度・経度、降車地点の緯度・経度、乗客の人数というデータを元に機械学習モデルを作成する。
学習用のデータの一部は以下の通り。

fare_amount pickup_longitude pickup_latitude dropoff_longitude dropoff_latitude passenger_count
2 5.7 -73.982738 40.761270 -73.991242 40.750562 2
3 7.7 -73.987130 40.733143 -73.991567 40.758092 1
4 5.3 -73.968095 40.768008 -73.956655 40.783762 1
6 7.5 -73.980002 40.751662 -73.973802 40.764842 1
7 16.5 -73.951300 40.774138 -73.990095 40.751048 1

バリデーション用データのうち、ある特徴量を互いに入れ替えてから、予測を実行して、損失関数の値がどう変わるかを観察する。
例えば、乗車地点の緯度を入れ替えてから予測をすると、予測結果は多く変わってくるから、損失関数の値も大きくなる、
一方で、乗客の人数は料金に影響しないので、乗客の人数を入れ替えても結果は殆ど変わらないだろうと予想される。

すなわち、精度が下がったらモデル構築の上で重要な特徴量、精度が下がらなかったらモデル構築の上で重要でない特徴量と判断できる。

Partial Dependence Plot (PDP)

2日目のテーマはPartial Dependence Plotである。
Partial Dependence Plotは、それぞれの特徴量が予測にどのような影響を与えるかを知るのに役に立つ。

資料はこちら。下の方のリンクから演習問題に行ける。
Partial Plots | Kaggle

モデルの訓練をしたあとに、
検証データのある点を元にして、影響を見たい1つの特徴量だけを変化させて、学習済みのモデルで予測を実施する。すると「1つの特徴量が変化すると予測はどう変わるのか?」が分かる。
検証データの中から多数の点について同様の操作を実施し、その平均を描画する。

演習問題の最後の方は、1日目のPermutation Importanceと2日目のPartial Dependence Plotを組み合わせた複合問題だった。これによって両者の挙動の違いが分かった。

問題:予測可能な特徴量が特徴量AとBの2つしかない場合を考える。どちらも最小値は-1、最大値は1である。
特徴量AのPartial Dependence Plotを描画すると、全ての範囲にわたって急激に増加する。一方、特徴量BのPartial Dependence Plotは、全ての範囲にわたってよりゆっくり(急激ではなく)増加する。
このとき、特徴量AのPermutation Importanceは必ず特徴量BのPermutation Importanceより必ず大きいと言えるか?

ちょっと考えると正しそうかなーっと思ったけど、実はこれは必ずしも正しくない。
たとえば、特徴量Aが変化する場合には大きな影響を与えるが、ほとんどのデータでは全く同じ値を取る、という場合が考えられる。この場合、Permutation Importanceを計算してもほとんどの値は変わらないままであり、特徴量AのPermutation Importanceの値はそれほど大きくならない。

pyconjp 2018 感想

PyCon JP 2018に行った。火曜日は有給休暇を取った。PyConJPは初参戦。大規模なカンファレンスってデブサミくらいしか行ったことなかったから、ある特定言語のカンファレンスは独特な感じがした。 (Rをほとんど使わないのにJapan.R 2016に行ったことはある)

資料や動画のリンクは以下の2つの記事でまとめてくれている。
PyCon_JP_2018カンファレンス資料まとめ(仮) - 筋肉で解決しないために。
【PyCon JP 2018】発表資料まとめ - Qiita

また、一部のセッションだけではあるが、ログミーTechに詳細な書き起こしが上がっている。 PyCon JP 2018の記事書き起こし - ログミーTech(テック)

【1日目】

基調講演 Argentina in Python: community, dreams, travels and learning

pythonを多くの人々に広めるために、車に乗って各地を回って講座を開催した人の話。すごい情熱だ。

東大松尾研流 実践的AI人材育成法

Twitterハッシュタグを追っている限りでは酷評されてた。 pythonの話というよりは機械学習人工知能の話をやたらと長く説明していた。普段Djangoとか触ってる人は「分からん……」だし、普段から機械学習に携わっている人は「長々と説明しなくてもええわ、退屈」になるし、加減が難しいな。 numpy力を判定する試験のシステムを開発したということなので、一般公開してほしい。

Webアプリケーションの仕組み

普段SIerのお仕事でWeb開発は全くやらないので、良い機会に勉強しとこうと思って聞いた。 まずはDjangoやFlaskのようなWebフレームワークを使わずに非常に単純なWebアプリケーションを書いてみて、少しずつ拡張する様子を実演していた。

Interpretable Machine Learning, making black box models explainable with Python!

機械学習システムで学習してみたは良いけど、そのモデルをどう解釈してよいか分からないのは問題である。モデルを解釈する主な手法を紹介する……という話。 Twitterで講演のjupyterリンクをツイートする、と講演者さんが当日は言ってたけど、結局ツイートしてないね(´・ω・`) David Low(@davidlowjw)さん | Twitter

Partial Dependence Plot (PDP)、Individual Conditional Expectation (ICE)、permutation によるFeature Importance、Local Surrogate Models (LIME)などの手法を説明していた。

この講演とは直接関係ないが、以下のサーベイ記事がまとまっていると思ったので、後で読んでおきたい。 【記事更新】私のブックマーク「機械学習における解釈性(Interpretability in Machine Learning)」 人工知能学会 (The Japanese Society for Artificial Intelligence)

Jupyterで広がるPythonの可能性

最初はメルカリのセッションに行こうとしたけど、満員で入れなかったので途中からこちらを聴講した。 内容がメチャクチャに盛りだくさんだったので追いつけなかった……これは手を実際に動かして習得したほうが良さそう。

Pythonistaの選球眼(せんきゅうがん) - エンジニアリングと野球の目利きになる技術

rettypy主催者の中川さんによる発表。私も2回ほど参加しております。 自分に馴染みのないWeb周りの話が主体だったのでちょっと感想が書きづらい。 主題となった「選球眼」すなわち「イシューからはじめよ」だが、自分は「イシューからはじめる」おとができているのかよく分からない……多分できていない気がする。 どのテーマについて何をどこまで作業するのかを明確にした上で始めましょう、手当たり次第に何でも飛びつくのはやめましょう、というやつだな。 俺自身の勉強は現在、基本的には機械学習周りだけとしているが、機械学習とひとくちに言っても、動画講座はあるわ、論文はあるわ、フレームワークは更新されるわ、と日々の更新が猛スピードで起きている。選択と集中が難しい……

【2日目】

Pythonでやってみた」:広がるプログラミングの愉しみ

気づいたら音声信号処理プログラミングになっていたので音声信号処理エンジニアの俺歓喜

  • プログラミングの動機は2種類 「面倒くさいことを簡単に」「一体どうなってるんだ? おもしろそう」
  • 作り始めるときには、最も単純な構成を考える! 最初から全部やろうとしないのがミソ。
  • 大事なのは、これらの技術を「学ぼう」とか「使おう」と思って制作をスタートしたわけではないということ。技術ドリブンじゃなくて、「何かをやりたい」と思って、あれこれ試行錯誤やってたら結果的に技術が身についた、というのが超大事。
  • 知識と学習は鶏と卵みたいな関係であり、「学習するためには知識がなきゃいけない」「知識を得るためには学習をしなきゃいけない」というジレンマがある。しかしどちらかを始めればあとはグルグル回り始める。

niconicoにおけるコンテンツレコメンドの取り組み

ニコニコの一人のユーザーとしては気づかないけど、色々なレコメンドシステムが裏側で動いているみたいだ。

Pythonistaに贈るコンテナ入門

同時刻にはGraphQLもあり、「なんだ、この時間帯はPythonに直接関係ないことも取り扱おうってセッションなのか?」と思いつつ聞いた。 Dockerは弊社内ではほとんどその名を聞かないのだが(SIだから?)、世の中的には既にかなり普及しているようなので、知っておかないとな、と思いつつ聞いた。

契約書データ関連のAI開発に伴う、前処理及び匿名化処理についての実例

センシティブな情報を扱う際の前処理や匿名化の問題。 発表者(CTO)が「まず私が10万件くらい手動でアノテーションしました」と言っていた。アノテーションがメチャクチャ大変そう。

1次元畳み込みフィルターを利用した音楽データのオートエンコーダ

ずいぶんストライドの大きい畳込みをしていたけど、あれってどういう効果があるんだろうか。音楽まわりの理論をよく分かってないまま実装しているように見受けられた。

料理写真が美味しく撮れる! 開発現場から覗くAI料理カメラの裏側

2月のデブサミでRettyの発表があり、そこでも「おいしく見える写真」を判別する機械学習システムを構築していた。Rettyでは機械学習させる際の教師データはは人力でラベルをつけたが、ヴァズ(サービス名SnapDish)では「いいねがたくさんついた投稿写真が美味しく見える写真」という手法をとっていた。あー、サービス運営してるとその手があるんだ!と思った。

ブース

アイシン精機が出てきたのが印象的で、「ずっと愛知県にいたけど、去年初めて東京都のお台場に開発拠点を立てました」って言っていて「あぁ、これは本気を出して新規事業に取り組もうとしているんだな」と感じた。 少し前に、デンソーが及川さんを技術顧問に迎えたというニュースを見たときも本気度を感じた。自動車業界の各社は、激しい変化にさらされて生き残りの道を探しているんだろう。

まとめ/おまけ

会場が1~6階にまたがっていたので結構移動が大変。 また部屋ごとに定員の数が大きく違うので、どのセッションをどの部屋に割り当てるのかは大変そう。(pyconjpの人がもしここを見ていたらお伝えしたいのですが、音声信号処理の分野は結構独特なので聞く人はそれほど多くないと思います。)

しかしそれを差し引いても、ためになる話が多く勉強になった。来年も参加しようと思う。 (あとはパーティーのときに話す相手がいなくてぼっちだったので……コミュニティに顔を出していろいろな人と知り合いになればいいのかな……?) まずは、1日目の「Jupyterで広がるPythonの可能性」の内容をもう一度見直して手を動かすことから始めようかと思う。 それでは。

画像セグメンテーション用のアルゴリズム、u-netについて簡単に説明する

きっかけ

kaggleであるコンペに参加しようとしてkernelを見たところ、みんな「u-net」ってアルゴリズムの話をしていた。聞いたことがなかったし全然分からなかったので調べてみた。

論文の著者が5分で簡単に説明している動画があるので、その内容をまとめる。
5 Minute Teaser Presentation of the U-net: Convolutional Networks for Biomedical Image Segmentation - YouTube

5 Minute Teaser Presentation of the U-net: Convolutional Networks for Biomedical Image Segmentation
youtube動画に対して、私が英語の文字起こしをして、さらに日本語訳の字幕を追加した。しかし現時点ではどちらも表示されていなくて悲しい……(誰かが字幕の審査をしてOKを出さないと表示されない。どなたか文字起こし・字幕の審査にOKを出してくれるとありがたい)

※この記事を書くにあたり、u-netの論文は読んでいません。ご注意ください。

概要、何に使うのか

u-netは画像のセグメンテーションのためのアルゴリズム。2015年に発表された。

手法のキモはどこか

u-netのアーキテクチャ(構成図)はこちら。
f:id:soratokimitonoaidani:20180924002248p:plain
これがU字型に見えるからu-netって名前なんですね、

3×3のkernelを用いて畳み込みをして、Max-poolingで縮小、という処理はCNNで一般的だ。その後、2×2のkernelを用いて拡大をして、元のサイズに戻す。
畳み込み→拡大という流れはAuto-Encoderと似ているのだが、縮小段階の途中の特徴量マップを、拡大段階の学習で再度使用するというのが最大の特徴である。

具体的に説明しよう。
図の上部に長い右向きの灰色矢印がある。矢印左側では、縮小段階の途中の568×568の特徴量マップが64枚ある。
矢印右側では、アップサンプリングしてきた392×392の特徴量マップが64枚ある(64という数字は直接登場しないが、結合結果が128枚であることから64枚と考えられる)。
縮小途中の64枚+アップサンプリングしてきた64枚 の合計128枚を結合(concatenate)したのちに入力として、次の特徴量マップ(390×390サイズ、64枚)を作る。
矢印の左右で画像サイズが異なるので、568×568から中央392×392だけを切り出して(crop)使用している。

通常のCNNは畳み込みでパディングをしているが、u-netの畳み込み時には、実行しない。
このため画像サイズが処理を経るごとに小さくなっていく。
(なんでパディングをしないのかは謎。kaggle上での実装を見てみると普通にパディングしてる例もある。)

先行研究と比べてどこがすごいか?

学習に使う画像の数が少なくても良いらしい。
あと学習および学習後の適用が高速である。(u-netは全結合の層が全く無いので、パラメータ数が小さい。それが速い理由だろうか?)

既存手法に比べて画像セグメンテーションの精度が良い。

参考

論文著者のサイト:
U-Net: Convolutional Networks for Biomedical Image Segmentation
機械学習の論文を日本語でまとめているarXivTimes上での説明:
U-Net: Convolutional Networks for Biomedical Image Segmentation - Issue #294 - arXivTimes/arXivTimes - GitHub

pythonのdillでは正規表現matchオブジェクトが保存できない

dillというのは、pickleの強化版のようなツールだ。現在使っている変数をまとめて外部のファイルに保存できる。
(バイナリにして保存することを、pickle化、シリアライズ、直列化などと呼ぶらしい)

dillについての情報はネットにあまり書いていない。下記の記事がとても参考になった。
Pythonですべての変数を保存するにはPickleよりdillが便利 - Qiita

余談ですが、「dill pickle」はピクルスの一種を指しているらしく、この語句で検索してもpythonのライブラリは出てきません。検索ワードに「python」を加えましょう。

dill pickle
《料理》ディル・ピクルス◆キュウリをディル(dill)の葉と種と共に塩漬けした物。
dill pickleの意味・用例|英辞郎 on the WEB:アルク

簡単な使い方

公式ドキュメントに使い方が載っていないので、ほぼ上記Qiitaそのままですが。

# dill_test_a.py
a = 123
b = 456
c = b - a
string = "Hello World"

import dill
dill.dump_session("session.pkl")

最後の2行で、現在の変数をすべて"session.pkl"というファイルに保存している。

# dill_test_b.py
import dill
dill.load_session("session.pkl")

print(a)
print(b)
print(c)
print(string)

'''出力:
123
456
333
Hello World
'''

保存した"session.pkl"から変数を復元し、その値を表示している。

pickleでは保存できないが、dillで保存できる例

上の例では単純な数値や文字列だけを保存(シリアライズ、直列化)した。
しかし、pythonには色々なオブジェクトがあり、pickleでは保存できないものもある。
今回の主題ではないし、私がきちんと理解していないので詳細は省くが、lambda関数、入れ子になった関数などがこれに該当する。dillではpickleを拡張子、lambda関数、入れ子になった関数なども保存できる。

公式の説明では、
12.1. pickle ? Python オブジェクトの直列化 - Python 3.6.5 ドキュメント の中の『12.1.4. pickle 化、非 pickle 化できるもの』
dillのreadme
を参照。

pickleオブジェクトがpickle化できるものの中で比較的、制限されているからです。つまり入れ子関数やlambda、スライスや、その他いろいろなものを処理できません。これらのオブジェクトを直接pickle化したいケースは、それほどはないかもしれませんが、pickle化したい他の物の中に、そういったオブジェクトが出てくることは、かなり一般的です。そのため、pickle化が失敗する原因となるのです。
私が選ぶ2015年の”新しい”Pythonモジュール トップ5 | POSTD

一部、pickle化できない種類のオブジェクトがある。
よく引っかかる例はlambda関数や、openで開いたファイルハンドラで、これが保存するオブジェクトのどこか1箇所にでも使われていると、pickle.dump()がエラーを出す。
pickle [いかたこのたこつぼ]

正規表現のマッチングオブジェクトが入っているとエラーになる

本題に入る。
色々なオブジェクトを保存できるdillだが、正規表現のmatchオブジェクトは保存できない。

import re
result = re.search("lar", "regular expression")
print(result)
print(type(result))

'''出力:
<_sre.SRE_Match object; span=(4, 7), match='lar'>
<class '_sre.SRE_Match'>
'''

"result"というmatchオブジェクトを作った。ではこれをdillで保存してみよう。

dill.dump_session("session2.pkl")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-07b38aa0950a> in <module>()
----> 1 dill.dump_session("session2.pkl")

D:\Code\Anaconda3\lib\site-packages\dill\dill.py in dump_session(filename, main, byref)
    331         pickler._recurse = False # disable pickling recursion for globals
    332         pickler._session = True  # is best indicator of when pickling a session
--> 333         pickler.dump(main)
    334     finally:
    335         f.close()

(長いので中略)

D:\Code\Anaconda3\lib\pickle.py in save(self, obj, save_persistent_id)
    494             reduce = getattr(obj, "__reduce_ex__", None)
    495             if reduce is not None:
--> 496                 rv = reduce(self.proto)
    497             else:
    498                 reduce = getattr(obj, "__reduce__", None)

TypeError: can't pickle _sre.SRE_Match objects

ダメだ。matchオブジェクトは保存できない。


解決方法

今回は、「matchオブジェクトも保存する」のではなく、「matchオブジェクトは保存できなくても良いから、その他のオブジェクトをまとめて保存する」ことを目指す。
つまり解決と言っているのは、具体的には「matchオブジェクト以外を保存する」ことである。

dump_session()関数に「指定した変数は除外する」という引数でも無いかなぁと思ったが、
公式ドキュメントを見てもそういう引数はない。
dill module documentation - dill 0.2.9.dev0 documentation

したがって、変数を削除してからdillを実行することにする。
変数の削除はdel [変数名]で実行できる。

import re
result = re.search("lar", "regular expression")
print(result)
print(type(result))

'''出力:
<_sre.SRE_Match object; span=(4, 7), match='lar'>
<class '_sre.SRE_Match'>
'''

del result
dill.dump_session("session2.pkl")

でresult以外の変数を保存できた。
保存したファイルを使用して変数を表示することもできた。(ソースコードは最初の例のファイル名を変えただけなので特に貼らない)

それでは。

Windows+Anaconda で環境切り替えしようとししてつまづいた2つのポイント

「scikit-learnとTensorFlowによる実践機械学習」の本を読み進めている。
TensorFlowのパートに入ったので、TensorFlowの環境を通常と別に構築しようとしたのでまとめておく
(なお最終的には失敗している。)

環境:
Windows 7 64bit
python --version

  • > Python 3.6.6 :: Anaconda 4.3.1 (64-bit)

Anacondaは環境管理もできる(のでvirtualenvを使う必要はない)

参考書では通常のpythonをインストールし、pipでパッケージ管理をしている。そして、隔離された環境を作成するためにvirtualenvを使うことを推奨している。
参考書に合わせてvirtualenvを使おうと思っていたが、調べてみると、Anacondaってパッケージの管理だけじゃなくて、環境の管理もできるということを知った。

condaは仮想環境管理にも使えます。: virtualenv/venvの代わり
仮想環境下でcondaやpipでパッケージをインストールできます。
condaで作る仮想環境はpythonバージョン違いまで吸収できるため、virtualenvの上位互換と言えます。
事実、anacondaでvirtualenvを使おうとすると、condaで環境を作るように警告が出ます。(virtualenvが作れはします。)
データサイエンティストを目指す人のpython環境構築 2016 - Qiita

「Condaの迷信と誤解」というタイトルの記事にはこう書かれている。

Reality: You actually can install (some) conda packages within a virtualenv, but better is to use Conda's own environment manager: it is fully-compatible with pip and has several advantages over virtualenv.
拙訳:実際には、virtualenvを通じてcondaのパッケージをインストールすることはできる。しかし、より良いのは、Conda事態の環境管理を使用することである。これはpipと完全に互換性があり、virtualenvと比べていくつかの利点がある。

Conda: Myths and Misconceptions | Pythonic Perambulations

なお、Condaで独立した環境を構築するためのコマンドに関しては、以下を参照。
Managing environments - Conda documentation


Powershellで切り替えが上手く行かない

PowerShellの上でactivateを実行すると、特にエラーなどは発生せず、正常に実行されたように見えるが、
実際には環境が切り替わっていないという不思議な事態が起きる。

解決策は
PowerShellでAnacondaの仮想環境をactivateするメモ - Qiita
に書いてあるとおり。以下のように打つとactivateが反映される。

conda install -n root -c pscondaenvs pscondaenvs

また、activateの際にエラーメッセージが表示され、実行できなかった。
activateでは「.ps1」 という拡張子のファイル(PowerShellスクリプト)を実行するが、デフォルトではスクリプトの実行は禁止されているからである。
管理者権限でPowerShellを立ち上げて、以下のように打つと「.ps1」拡張子のファイルを実行できる。

Set-ExecutionPolicy RemoteSigned