|

Hy による Rescale で Keras を使用したニューラル ネットワーク

長い間 GNU Emacs ユーザーさん、取りに来ました C-x C-e (eval-last-sexp)当然のことです。 つまり、編集しているほぼすべてのファイルで、どこにでも括弧式を挿入できます。 C-x C-e、ミニバッファ (または、LISP でプログラミングしている場合は REPL) に表示される結果を取得します。
他の多くの言語はコンソール インターフェイスまたは REPL を提供しますが、それらは通常、言語の独立した機能として提供されます。 想定される インタラクションのモード。 これが表面的な観察であることは認めますが、この用語をユーザー インタラクションに対する「スクリプト中心」または「REPL 中心」のアプローチと言い換えることもできます。 新しいプログラミング言語を学習している自分を想像してみてください。 「スクリプト中心」のアプローチでは、ターミナル (または IDE) から hello world プログラムを実行する方法がすぐにわかりますが、「REPL 中心」のアプローチでは、REPL にドロップして必要な式を評価する方法がすぐにわかります。 Hello World 効果を実現します。
言い換えれば、「スクリプト中心」のアプローチは概念的に編集と評価のサイクルを分離しますが、「REPL中心」のアプローチは表現、評価、フィードバックの単一の流れを中心に設計されています。 各方法には長所と短所がありますが、プロトタイピングや実験では、カーソルの位置でコードを評価することで得られる「コードを操作している」という感覚に勝るものはありません。 Emacs では、Lisp ファミリーの言語では、これが一般に期待される対話方法です。
これをどのように実証できるでしょうか? さて、私の同僚、マーク チュートリアルを書いた XNUMX 月に Keras トレーニング ジョブをセットアップしたときのことです。 それ以降、ソフトウェアは更新されているため、そのジョブの更新バージョンを作成します。 ただし、生の Python の代わりに、 ヒラン、これは基本的に Python インタープリター用の lisp.

Emacs の最新バージョン (バージョン 24 以降など) が Emacs で実行されていると仮定します。 パッケージマネージャーのセットアップ、インストールしたいと思うでしょう ハイモード (M-x package-install RET hy-mode RET)、および多くの厄介な括弧パッケージの XNUMX つ、たとえば パレディ, スマートパレンズ, 舌足らずな.
新しいファイルでは、 cifar10_cnn.hyがオンになっていることを確認してください Hy モード。 次に、使用します M-x inferior-lisp ハイレップを始めるには! 一番下までスクロールすると、Emacs インタラクションのビデオデモが表示されます。

1. まず、インポートを処理しましょう 

1.1 パイソン

__future__ から print_function をインポート keras.datasets からインポート cifar10 keras.models からインポート シーケンシャル keras.layers.core からインポート Dense、Dropout、Activation、Flatten keras.layers.convolutional からインポート Convolution2D、MaxPooling2D keras.optimizers からインポート SGD、Adadelta、Adagrad keras.utils から np_utils をインポートし、six.moves からの generic_utils インポート範囲

1.2 これを hy で書き直すと次のようになります。

(import [__future__ [print_function]] [keras.datasets [cifar10]] [keras.models [Sequential]] [keras.layers.core [Dense Dropout Activation Flatten]] [keras.layers.convolutional [Convolution2D MaxPooling2D]] [keras .optimizers [SGD Adadelta Adagrad]] [keras.utils [np_utils generic_utils]] [six.moves [range]] [numpy :as np])

51 語から 39 語まで。簡潔さとしては悪くありません。

2. 次に定数を書き換えてみましょう

2.1 パイソン

バッチ_サイズ = 32 nb_classes = 10 nb_epoch = 100 # 入力画像のサイズ img_rows, img_cols = 32, 32 # CIFAR10 画像は RGB img_channels = 3

2.2 ハイ

(def batch_size 32 nb_classes 10 nb_epoch 100 ;; 入力画像の寸法 img_rows 32 img_cols 32 ;; CIFAR10 画像は RGB img_channels 3)

Hylang は以下からインスピレーションを受けています Clojureのただし、Clojure とは異なり、複数の変数が許可されます defデフォルトでは -s です。 この場合、非常に便利です。

3. 機能

Note that the input_shape 引数の順序は以前のバージョンから変更されました。 (channels, rows, columns) 〜へ (rows, columns, channels)

3.1 パイソン

def load_dataset(): # データ、シャッフルされ、トレーニング セットとテスト セットの間で分割されます (X_train, y_train), (X_test, y_test) = cifar10.load_data() print('X_train Shape:', X_train.shape) print(X_train. shape[0], 'train tables') print(X_test.shape[0], 'test tables') # クラスベクトルをバイナリクラス行列に変換します Y_train = np_utils.to_categorical(y_train, nb_classes) Y_test = np_utils.to_categorical(y_test, nb_classes) X_train = X_train.astype('float32') X_test = X_test.astype('float32') X_train /= 255 X_test /= 255 return X_train、Y_train、X_test、Y_test def make_network():model = Sequential() モデル。 add(Convolution2D(32, 3, 3, border_mode='same', input_shape=(img_rows, img_cols, img_channels))) model.add(Activation('relu')) model.add(Convolution2D(32, 3, 3) )model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(Dropout(0.25))model.add(Convolution2D(64, 3, 3, border_mode= '同じ'))model.add(Activation('relu'))model.add(Convolution2D(64, 3, 3))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2) 、2)))model.add(Dropout(0.25))model.add(Flatten())model.add(Dense(512))model.add(Activation('relu'))model.add(Dropout(0.5) ) model.add(Dense(nb_classes)) model.add(Activation('softmax')) return モデル def train_model(model, X_train, Y_train, X_test, Y_test): sgd = SGD(lr=0.01,decay=1e-6) 、勢い = 0.9、nesterov = True) model.compile(loss = 'categorical_crossentropy'、optimizer = sgd) model.fit(X_train、Y_train、nb_epoch = nb_epoch、batch_size = batch_size、validation_split = 0.1、show_accuracy = True、verbose = 1 ) print('テスト中...') res = model.evaluate(X_test, Y_test,batch_size=batch_size,verbose=1, show_accuracy=True) print('テスト精度: {0}'.format(res[1]) ) def save_model(model): model_json = model.to_json() open('cifar10_architecture.json', 'w').write(model_json) model.save_weights('cifar10_weights.h5', overwrite=True)

3.2 ハイ

以下のコードでは、変数を構造化して書くことができます。 TRAIN & TEST 次のような単一ステップで:
(let [ [[X-train y-train] [X-test y-test]] (cifar10.load_data) ] )

 

(defn load-dataset [] ;; シャッフルされ、トレーニング セットとテスト セットに分割されたデータ (let [[TRAIN TEST] (cifar10.load_data) [X-train y-train] TRAIN [X-test y-test] TEST) ;; クラス ベクトルをバイナリ クラス行列に変換します Y-train (np_utils.to_categorical y-train nb_classes) Y-test (np_utils.to_categorical y-test nb_classes)] (print "OK") (print "X_train Shape: " X-train .shape) (print (get X-train.shape 0) "トレーニング サンプル") (print (get X-test.shape 0) "テスト サンプル") ;; hy タプル表記 (, X-train Y-train X- test Y-test))) (defn make-network [] (doto (Sequential) (.add (Convolution2D 32 3 3 :border_mode "same" :input_shape (, img_rows img_cols img_channels))) (.add (Activation "relu") )) (.add (Convolution2D 32 3 3)) (.add (Activation "relu")) (.add (MaxPooling2D :pool_size (, 2 2))) (.add (Dropout 0.25)) (.add (Convolution2D 64) 3 3 :border_mode "same")) (.add (アクティベーション "relu")) (.add (Convolution2D 64 3 3)) (.add (アクティベーション "relu")) (.add (MaxPooling2D :pool_size (, 2 2) ))) (.add (Dropout 0.25)) (.add (Flatten)) (.add (Dense 512)) (.add (Activation "relu")) (.add (Dropout 0.5)) (.add (Dense nb_classes) )) (.add (Activation "softmax")))) (defn train-model [モデル X-train Y-train X-test Y-test] (let [sgd (SGD :lr 0.01 :decay 1e-6 :momentum) 0.9 :nesterov true)] (doto モデル (.compile :loss "categorical_crossentropy" :optimizer sgd) (.fit X-train Y-train :nb_epoch nb_epoch :batch_size バッチサイズ :validation_split 0.1 :show_accuracy true :verbose 1))) (print "テスト中...") (let [res (model.evaluate X-test Y-test :batch_size バッチサイズ :verbose 1 :show_accuracy true)] (-> "テスト精度 {}" (.format (get res 1)) (print)))) (defn save-model [model] (with [ofile (open "cifar10_architecture.json" "w")] (ofile.write (model.to_json))) (model.save_weights "cifar10_weights.h5" :上書き true))

使い方に注目してください doto これにより、繰り返しの代入が非常に簡単になります。 式はその内部の最終形式に評価されるため、それは によって渡されます。 doto、私たちのモデルのセットアップ make-network 変数名さえ必要ありません。
Hylang は、便利なスレッド マクロ (->) もサポートしています。 Clojureこれにより、ステートメントを簡単に連鎖させることができます。 この例では、フォーマット文字列を単に .format 関数を選択して印刷します。

4. メインランナーブロック

4.1 パイソン

if __name__ == '__main__': X_train, Y_train, X_test, Y_test =load_dataset() model = make_network() train_model(model, X_train, Y_train, X_test, Y_test) save_model(model)

4.2 ハイ

(when (= --name-- "__main__") ;; 再現性のために追加 (np.random.seed 1) (let [[X-train Y-train X-test Y-test] (load-dataset)] ( doto (make-network) (train-model X-train Y-train X-test Y-test) (save-model))))

5. 簡単なビデオ

この短いビデオでは、結果をロードする方法を確認できます。 hylang ファイルを emacs に読み込み、hy REPL を通して実行し、その時点でステートメントを評価します (次のように表示されます)。 ^X ^E キーオーバーレイ内)、それ以外の場合は、REPL と編集バッファーの間を行き来します。
最後のほうで、私がいかに見逃していたかがわかります。 numpy インポート、インポートをに追加しました (import ...) フォームを修正し、インポート フォーム全体を再評価しました。 カーソルをフォームの最後に移動して使用しました eval-last-sexp式を評価するために使用することもできますが、 Ctrl Alt x or lisp-eval-defun、これはカーソルを囲む最上位の式を評価します。
Since load-dataset & make-network 引数を取らない場合は、関数本体を でラップすると便利です。 let or doto 表現(または フォーム)、その時点でブロックを繰り返し評価し、REPL 出力をチェックし、満足したらラップします。 let にブロックする defn フォーム。

6. プラットフォーム上で実行する

実際のモデルのトレーニングを開始するとすぐにビデオが停止します。これは、コンピューターに優れた GPU が搭載されておらず、トレーニングに時間がかかるためです。 したがって、代わりに、それを Rescale プラットフォームに戻して完了します。最初に、 hy 実行によるコンパイラ

 

pip install git+https://github.com/hylang/hy.git

それから単に電話するだけです hy cifar10_cnn.hy Mark の以前の出力例を複製します。
(この例では、hylang の最新バージョン (バージョン 0.11.0、コミット 0abc218) を GitHub から直接実行していることに注意してください)。 hy を使用してインストールした場合 pip install hy 古い割り当てを使用している可能性があります let/with 構文。
すぐに実行できるサンプルが見つかります こちら。 さらに、この投稿の具体的なバージョンが見つかります。 githubで.

7. ダジャレはごめんなさい

でも、そろそろ時間かな? ご覧のとおり、Emacs への REPL の統合には癖があります。 成熟したデバッグ ツールのサポートが少ないため、深いスタック トレースからのエラーのデバッグも少し困難になります。 しかし、LISP の操作が好きで、Python エコシステムを使用したい、または使用する必要がある場合は、hy は Web 開発、機械学習、または単純なテキスト解析に使用できる、機能的で強力で楽しいツールです。 組み合わせることもできると言いましたね hy ファイルと py ファイル?

類似の投稿