Translate

2018年2月23日金曜日

TesnorFlowの乳がんデータ分類器チュートリアルを翻訳してみた。

Twitterのタイムラインに以下の記事が流れてきた。



ので、読んでみたら、比較的読みやすい内容だったので、
翻訳してみた。
以下、at your own riskで参照してください。
--------

乳がん検出用ニューラルネットを簡単に構築できます


機械学習と人工知能があなたのプログラム方法を変えるでしょう。それは確かに学習に値するコーディングにおける基本的な変化です。最初はちょっと大変です - 物事を行うアルゴリズムを書くのではなく、代わりにマシンを訓練するのですから。

ふつうは、コンセプトカウント、つまり生産性を高めるために理解しなければならない新しいコトの数は、少しばかりなんです。そのことを念頭に置いて、私は、あなたを導くためのチュートリアルを書こうと思っていました。それが、細胞スキャンで乳がんを検出するニューラルネットワークです!

今回はCSVファイルとなっている構造化データを扱います。これは、生検で採取された細胞の画像を精密に検査して生成されたものです。また、画像を直接操作することも可能ですが、ここではこのアプローチを選択しました。このチュートリアルコードを変更すれば、気になる問題を修正することができるからです。癌検出に取り組んでいない可能性があります。うまくいけば、ここで使うテクニックもあなたのためになるでしょう!

私は 悪性または良性細胞の数値を持つ新しい列を作成するためにここで利用できるデータを少し調整して使用しました。修正されたデータセットはここにあります。

私はこのチュートリアルをできるだけシンプルで再利用できるようにしようとしました。他のデータがあれば、このコードを修正してニューラルネットワーク分類器を構築するのは比較的簡単です。


フィーチャーとラベルを理解する

本題に入る前に、「フィーチャー」と「ラベル」について詳しく説明させてください。ちょっと混乱するかもしれませんけど。

「フィーチャ」をデータの属性と考えてください。このチュートリアルで使用する乳癌データベースの場合は、細胞の大きさや形などです。電子メールを扱うのであれば、フィーチャーは送信者、件名、メール本文などになります。

「ラベル」は、予測または分類したいデータの属性と考えることができます。乳がんの場合、細胞が良性か悪性かを知りたいので、これがラベルになります。電子メールの例だと、メールが迷惑メールかどうかをラベルにすることができます。

ニューラルネットをトレーニングするプロセスは非常に簡単です。あなたは、フィーチャーとラベルを含むデータの束を用意します。そして、それをトレーニングセットとテストセットに分割します。

あなたのトレーニングセットから、あなたのフィーチャーを取り分け、対応するラベルが何であるかをニューラルネットに伝えます。損失関数と入力関数(これらについては次のチュートリアルで詳しく説明しています)に基づいて、ラベルを決定するフィーチャを使って学習します。

学習が終わったら、テストセットで試してみましょう。ここでは、ラベルの内容を予測し、正解ラベルの内容と比較します。これから、その正答率(accuracy)を判断することができます。


TensorFlow を使ってニューラルネットワークを構築する

理論的な話は十分ですね、ではコーディングをはじめましょう!それが学ぶための最善の方法の1つなのです。私は TensorFlow を使ってNeural Netをビルドしてテストました。Pythonをメインのプログラミング言語としてトレーニングやテストを実行します。

まず、必要なライブラリをインポートしましょう:


import tensorflow as tf
import pandas as pd
import numpy as np
pandas numpy は大量の数値計算やデータ管理をサポートしてくれるPythonのライブラリです。

次に、プログラムのさまざまな側面についていくつかの変数を作成しましょう。私はコードをより移植性の高いものにするためにこれらを最初に記述することが好きです。


# データはトレーニングセットとテストセットに分割する必要があります
# 80/20を使用するには、トレーニングのサイズを.8に設定します
training_set_size_portion = .8

# トレーニングセットとテストセットに分割する前に、データをシャッフルするには
# この値をTrueに設定します
do_shuffle = True
# 正解率(accuracy)スコアを記録する変数
accuracy_score = 0
# DNNにはユニットが隠されており、ここにその仕様が設定されています
hidden_units_spec = [10,20,10]
n_classes_spec = 2
# モデルとチェックポイントを保持するための一時ディレクトリを定義する
tmp_dir_spec = "tmp/model"
# トレーニングのステップ数
steps_spec = 2000
# epoch数
epochs_spec = 15
# ファイル名 - アップロードする場合はこれを必ず変更してください
file_name = "wdbc.csv"

# ここにフィーチャーセットがあります。
# CSVには、カラムの名前が表示されます。
# ここでは、これらのすべてを使用します(半径とテクスチャ)。
features = ['radius','texture']

# 予測するラベルは次のとおりです -- CSVの列でもあります(診断値)
labels = ['diagnosis_numeric']

# データを提供するファイル名は次のとおりです
data_name = 'wsbc.csv'

# データの入手もとURLは次のとおりです
data_url = 'http://www.laurencemoroney.com/wp-content/uploads/2018/02/wdbc.csv'
私はこのようにしてコードを非常に汎用的にしています。乳がんのデータに興味がない場合  は、これらの値、特にfeature_keyslabel_key、およびデータの場所(data_namedata_url)を変更してください。

では、データをロードしましょう:


file_name = tf.keras.utils.get_file(data_name, data_url)
my_data = pd.read_csv(file_name, delimiter=',')
簡単でしたね。



指定した列に基づいてトレーニングとテストセットを作成する

あなたのデータにはすでに何らかの形の順番があり、これは学習/テストに影響を与える可能性があります。たとえば、乳がんでサイズ別に分類され、最初のd報のデータが良性であり最後の方が悪性である可能性が高い場合は、良性のデータを中心にトレーニングしてしまい、テスト対象がほとんど悪性になってしまいます。トレーニングとテストセットに分割する前に、データをシャッフルすることは、一般的には良いアイデアなのです:

# pandas の DataFrame を使用すると、再インデックスメソッドをシャッフルできます
# Docs: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.reindex.html#pandas.DataFrame.reindex
# doShuffleプロパティがtrueの場合、これをシャッフルします
# 本当にデータの傾向があなたの学習に影響しないことを確認するためにシャッフルするべきですが、
# ここではオプションにしています
if do_shuffle:
 randomized_data = my_data.reindex(np.random.permutation(my_data.index))
else:
 randomized_data = my_data
データをランダム化したら、次に分割します。先ほどトレーニングサイズの部分を指定したので、それに基づいてトレーニングセットに含めるレコードの数を計算し、残りはテストセットにします。このコードは、各セットのサイズを提供しています...

total_records = len(randomized_data)
training_set_size = int(total_records * training_set_size_portion)
test_set_size = total_records = training_set_size
...このコードでは、トレーニングフィーチャとラベルに指定したサイズに基づいて、データをトレーニングフィーチャとラベルセットに分割します。私たちはrandomized_data の'head' (頭) から取っていきます。

# トレーニングフィーチャとトレーニングラベルの構築
training_features = randomized_data.head(training_set_size)[features].copy()
training_labels = randomized_data.head(training_set_size)[labels].copy()
print(training_features.head())
print(training_labels.head())
同様に、 'tail' (お尻)のレコードにはテストセットが含まれています。test_set_size 分を取っていきます。

# テストフィーチャとテストラベルの構築
testing_features = randomized_data.tail(test_set_size)[features].copy()
testing_labels = randomized_data.tail(test_set_size)[labels].copy()


TensorFlow フィーチャカラムを作成する

ニューラルネットワーク分類器は、フィーチャカラムが tf.feature_column 型として指定する必要があります。ろれらのカラムはぜんぶ数値なので、numeric_column 型に設定します。

feature_columns = [tf.feature_column.numeric_column(key) for key in features]

データを分類するために使用されるニューラルネットワークを定義する

私たちがすべてのデータを持っていることを考えれば、データをトレーニングするニューラルネットワークオブジェクトを作成できます。これは、作成したばかりのフィーチャカラムと、ニューラルネットワークの隠れユニットの数を定義するパラメータ、およびクラスの数を引数として取ります。ネットワークをトレーニングするときに、一時ファイルとチェックポイント、および完成したモデルを指定されたモデルディレクトリに保存します。

隠れユニットは、ネットワークがどのように見えるかを直接的に指定したものです。例えば、ここでのデフォルトは [10,20,10] です。つまり、10個のニューロンの層があり、それぞれ20個のニューロンに接続されます。そして次の層である第3層の10個のニューロンに接続されます。

クラスは、私たちが分類しているクラスの(分類)数です。このケースでは、2つのクラスで乳がん分類を行っているので、2つのクラスをトレーニングします。


classifier = tf.estimator.DNNClassifier(
    feature_columns=feature_columns,
    hidden_units=hidden_units_spec,
    n_classes=n_classes_spec,
    model_dir=tmp_dir_spec)


ネットワークをトレーニングする

次のステップは、データ使って分類器をトレーニングすることです。これを行うには、フィーチャー(別名 'x')とラベル(別名'y')を指定する入力関数を作成します  。これは pandas_input_fn として指定することによって行われます。

# トレーニング入力関数の定義
 train_input_fn = tf.estimator.inputs.pandas_input_fn(x=training_features, y=training_labels, num_epochs=epochs_spec, shuffle=True)
そしてニューラルネットワークに、入力関数と、それをトレーニングするために使用したいステップの数を与えることで、トレーニングを開始することができます。異なる結果を得るために異なるステップ数を試してみてください。2000ステップの乳がんデータの場合、私は通常、テストセットに対して 90% 以上の精度を得ることができました。

# 分類器を使ってモデルをトレーニングする
 classifier.train(input_fn=train_input_fn, steps=steps_spec)

ネットワークをテストする

モデルのトレーニングと同様に  テストフィーチャーとテストラベルを渡す以外は、まったく同じ方法で入力関数を指定することで、我々はモデルをテストします:

# テスト入力関数の定義
 test_input_fn = tf.estimator.inputs.pandas_input_fn(x=testing_features, y=testing_labels, num_epochs=epochs_spec, shuffle=False)
つぎに、分類器にテスト入力関数を評価させ、正解率を取得します。テストセットを渡し、分類結果を実際の値と比較し、これを使って正解率(accuracy)を計算し、正確なスコアを表示します:
# 正解率(accuracy) を評価する
 accuracy_score = classifier.evaluate(input_fn=test_input_fn)["accuracy"]
 print("Accuracy = {}".format(accuracy_score))
この時点で、ネットワークのトレーニングパラメータを調整して、ネットワークをトレーニングするための最良の値が何であるか把握することができます。場合によっては、適切なフィーチャーカラムをニューラルネットワークに与えていない場合があるかもしれません。また、ステップ数やネットワーク層の設定などを微調整することもできます。これは TensorFlow の素晴らしい点です。このように簡単に作業できます!

ネットワークを使用する

トレーニングを受けたテスト済みのネットワークが完成したので、まだ未投入のさまざまなデータセットを予測するためにどのように反応するかを見たいでしょう。それを実行する方法を実行して、ここで結果を読んでみましょう。

まず、予測セットはフィーチャー列と一致しなくてはなりません。したがって、このチュートリアルでは2つのフィーチャカラムに対してのみトレーニングを行い、しかも両方とも数値でした。このため予測セットで分類したいのであれば、同じ型式のデータをネットワークに渡す必要があります。たとえば、次のコードでは、半径14・テクスチャ25、半径13・テクスチャ26の2つのセルの予測セットを作成しています:


# 予測セットの作成 -- 分類させたい入力フィーチャーのリスト
prediction_set = pd.DataFrame({'radius':[14, 13], 'texture':[25, 26]})
そしてトレーニングやテストと同様に、入力関数を指定しますが、予測を始めるのでラベル(引数'y')がないので、ラベルを戻すことを期待して入力を指定します:
predict_input_fn = tf.estimator.inputs.pandas_input_fn(x=prediction_set, num_epochs=1, shuffle=False)
分類機はこの関数にもとづいてラベルを予測します。

# 予測結果のリストを取得する
predictions = list(classifier.predict(input_fn=predict_input_fn))
この処理はたくさんのデータを返しますが、私たちの分類は'classes'として保存されるので、それらを抽出してprintすることができます:

predicted_classes = [p["classes"] for p in predictions] results=np.concatenate(predicted_classes) print(results)

まとめ

ウィスコンシンのデータベースから乳がんのデータを分類するためにニューラルネットワークをトレーニングしただけでなく、あらゆるCSVファイルの分類を容易に行うことができるコードを作成しています。ぜひためして下のコメント欄にあなたの経験を書いて教えてください(元サイトにはコメント機能がある)!

--------

Estimator、入力関数の時代になったので、本家サイトのチュートリアルもそろそろかわるかもなあ..

2018年2月6日火曜日

TensorFlow 1.6.0-rc0 の案内がタイムラインに..

つい先日 1.5.0のコンテナに差し替えたばかりだというのに
今日ふとタイムラインをのぞくと..


えーっ、もう1.6.0-rc0かよ...

とりあえずリリースノートを確認してみた。
以下、勝手翻訳なので参照される方は at your own riskでお願いします。

-------

TensorFlow 1.6.0-rc0

Assets




リリース1.6.0

Breaking Changes

予めビルドされたバイナリは、CUDA 9.0およびcuDNN 7に対して構築されています。 
事前ビルドされたバイナリはAVX命令を使用します。古いCPUでTFが破損する可能性があります。


主な機能と改善点

  • tf.estimator.{FinalExporter,LatestExporter}今すぐ削除されたSavedModelsをエクスポートします。これにより、SavedModelの前方互換性が向上します。 
  • XLA CPU / GPUにFFTサポートが追加されました。

バグ修正やその他の変更


  • ドキュメントの更新:
    • ML入門者を対象としたGetting Startedの第2版が追加されました
    • resize_images.align_cornersパラメータに関する明確な文書
    • TPUの追加ドキュメント。
  • Google Cloud Storage(GCS):
    • クライアント側のスロットルを追加します。
    • FileSystemインターフェイスにFlushCaches()メソッドが追加、これはGcsFileSystemに実装されています
  • その他:
    • 非スロット変数用の新しいオプティマイザ内部API。_beta [12] _powerにアクセスするAdamOptimizerの派生は更新する必要があります。
    • tf.contrib.distributions.Kumaraswamyを追加。
    • RetryingFileSystem::FlushCaches()はベースFileSystemのFlushCaches()を呼びます
    • ディストリビューションにauto_correlationを追加します。
    • tf.contrib.distributions.Autoregressiveを追加。
    • SeparableConv1D レイヤを追加。
    • 畳み込み Flipout レイヤを追加。
    • tf.matmulの両方の入力が bfloat16 の場合、float32の代わりにbfloat16を返却。
    • tf.contrib.image.connected_componentsを追加。
    • tf.contrib.framework.CriticalSectionを追加し原子変数アクセスを可能に
    • 分類タスクのためのツリー予測に対する出力分散。
    • ptコマンドおよびevalコマンドのために、テンソル値をファイルシステムにnumpyファイルとして書き込むことが可能に。
    • gRPC:(gRPCの内部エラーを返す代わりに)切り捨てエラーを伝播。
    • 2種類のプリフェッチをサポートするためにparallel_interleaveを拡張。
    • C64関連のログ、pow、atan2、tanhに対するXLAサポートの改善。
    • 確率論的畳み込み層を追加する。

APIの変更

  • 下位互換性のため、デフォルト設定をFalseにしたprepare_varianceブール値を導入。
  • layers_dense_variational_impl.pylayers_dense_variational.pyへ移動。

既知のバグ

  • XLAを使用すると:CUDA 9およびCUDA 9.1でGPUを実行すると、ゴミの結果CUDA_ILLEGAL_ADDRESS失敗が発生
Googleは、2017年12月中旬に、CUDA 9 とCUDA 9.1 のPTX-SASSコンパイラが、大規模なオフセット(たとえばload [x + large_constant] )のある64ビットアドレス計算をSASSの32ビット算術に分解するときにキャリービットを正しく計算しないことがあることを発見しました。

その結果、これらのバージョンでは 、4GB以上の一時メモリ ptxas を使用するほとんどのXLAプログラムが誤ってコンパイルされます。その結果、ゴミの結果や CUDA_ERROR_ILLEGAL_ADDRESS 失敗が発生します。

CUDA 9.1.121の修正は2018年2月下旬に予定されています。CUDA 9.0.xの修正は予定されていません。修正が利用可能になるまで、唯一の回避策はCUDA 8.0.x にダウングレードするか、XLA:GPUを無効にすることです。

TensorFlowは、XLA:GPUとCUDAの間違ったバージョンを使用している場合は警告を表示します。e00ba24を参照してください。
謝辞
このリリースにはGoogle社の方々同様以下の方々の貢献が含まれています。

4d55397500, Ag Ramesh, Aiden Scandella, Akimasa Kimura, Alex Rothberg, Allen Goodman,
amilioto, Andrei Costinescu, Andrei Nigmatulin, Anjum Sayed, Anthony Platanios,
Anush Elangovan, Armando Fandango, Ashish Kumar Ram, Ashwini Shukla, Ben, Bhavani Subramanian,
Brett Koonce, Carl Thomé, cclauss, Cesc, Changming Sun, Christoph Boeddeker, Clayne Robison,
Clemens Schulz, Clint (Woonhyuk Baek), codrut3, Cole Gerdemann, Colin Raffel, Daniel Trebbien,
Daniel Ylitalo, Daniel Zhang, Daniyar, Darjan Salaj, Dave Maclachlan, David Norman, Dong--Jian,
dongsamb, dssgsra, Edward H, eladweiss, elilienstein, Eric Lilienstein, error.d, Eunji Jeong, fanlu,
Florian Courtial, fo40225, Fred, Gregg Helt, Guozhong Zhuang, Hanchen Li, hsm207, hyunyoung2,
ImSheridan, Ishant Mrinal Haloi, Jacky Ko, Jay Young, Jean Flaherty, Jerome, JerrikEph, Jesse
Kinkead, jfaath, Jian Lin, jinghuangintel, Jiongyan Zhang, Joel Hestness, Joel Shor, Johnny Chan,
Julian Niedermeier, Julian Wolff, JxKing, K-W-W, Karl Lessard, Kasper Marstal, Keiji Ariyama,
Koan-Sin Tan, Loki Der Quaeler, Loo Rong Jie, Luke Schaefer, Lynn Jackson, ManHyuk, Matt Basta,
Matt Smith, Matthew Schulkind, Michael, michaelkhan3, Miguel Piedrafita, Mikalai Drabovich,
Mike Knapp, mjwen, mktozk, Mohamed Aly, Mohammad Ashraf Bhuiyan, Myungjoo Ham, Naman Bhalla,
Namrata-Ibm, Nathan Luehr, nathansilberman, Netzeband, Niranjan Hasabnis, Omar Aflak, Ozge
Yalcinkaya, Parth P Panchal, patrickzzy, Patryk Chrabaszcz, Paul Van Eck, Paweł Kapica, Peng Yu,
Philip Yang, Pierre Blondeau, Po-Hsien Chu, powderluv, Puyu Wang, Rajendra Arora, Rasmus, Renat
Idrisov, resec, Robin Richtsfeld, Ronald Eddy Jr, Sahil Singh, Sam Matzek, Sami Kama, sandipmgiri,
Santiago Castro, Sayed Hadi Hashemi, Scott Tseng, Sergii Khomenko, Shahid, Shengpeng Liu, Shreyash
Sharma, Shrinidhi Kl, Simone Cirillo, simsicon, Stanislav Levental, starsblinking, Stephen Lumenta,
Steven Hickson, Su Tang, Taehoon Lee, Takuya Wakisaka, Ted Chang, Ted Ying, Tijmen Verhulsdonck,
Timofey Kondrashov, vade, vaibhav, Valentin Khrulkov, vchigrin, Victor Costan, Viraj Navkal,
Vivek Rane, wagonhelm, Yan Facai (颜发才), Yanbo Liang, Yaroslav Bulatov, yegord, Yong Tang,
Yoni Tsafir, yordun, Yuan (Terry) Tang, Yuxin Wu, zhengdi, Zhengsheng Wei, 田传武

--------
いろいろ改変はあるが、これはいつもどおりなので
おそらく今回のヤマは既知バグの話だろう。

CUDA9.1系を使っているなら最新版でバグが治りそうだが、
CUDA9.0系の人はダウングレードしか今のところ回避法がないというところは
記憶しておこう。

初心者にとってはTensorFlow本家サイトのチュートリアルを始めとした
ドキュメントが改変になっているところが大きい。

正直初期のドキュメントは本気で機械学習を始めている研究者向けだった。
数式も多かったし..
 #パラ味しかしてないけど、数式は減った気がする..

おそらく正式版の1.6.0は上記よりもっといろいろ盛り込まれることだと思う
実際1.5.0rc0から1.5.0正式版でもだいぶ変更がはいっていたし。





 



p.s.

まあ、なんにせよ動かしてみようかな..と
これまで動かしていたGPU版 Tensorflow1.5.0(python3)の公式Dockerコンテナ を潰し
tensorflow/tensorflow:1.6.0-rc0-gpu-py3 イメージを立ち上げて
tensorflow をインポートしようとしたら..



..うごかん..

CPU版もだめ...


...
しばらく静観しよっと...

プレイステーション3コントローラをRaspberry Piで使う

家でせっせと Donkey Car をつくっているのだけど やっぱりジョイスティックがほしい.. 学習データのために自分でうまく運転しないとだめなのだけど スマホでの操作は難しい.. Donkey Carドキュメントによると 機械学習データは 10分から15分程...