近日,機器之心發現一個非常有意思的工具,可以用視覺化的方式輕鬆新增摺積層、全連線層和池化層等層級,然後生成可執行的 TensorFlow 程式碼。此外,我們也嘗試搭建一個簡單的卷積架構,並在本地 TensorFlow 環境下測試生成的程式碼。
工具地址:https://www.tensoreditor.com/
TensorEditor 是一個強大的機器學習工具,甚至小白都能以視覺化的方式快速生成整個模型的程式碼。通過 TensorEditor,小白可以連線卷積層、全連線層和池化層等視覺化結點建立整個模型,且我們可以將它們轉化為 TensorFlow 和 Python 程式碼,並進一步在自己的環境中執行。
基本上,TensorEditor 的步驟即定義我們的資料集、影像或特徵,然後建立深度神經網路並下載 Python 2.7 的程式碼,最後就需要在我們自己的 TensorFLow 環境下執行就好了。
通過 TensorEditor,我們不僅可以建立深度網路並避免一些常見的程式碼問題,同時還能生成基於 TensorFlow Estimator 的高效程式碼。如下所示,機器之心嘗試構建了一個簡單的卷積網路,我們使用了兩個卷積層、兩個池化層和一個全連線層,並在最後的 Estimator 使用了交叉熵損失函式和 Adagrad 最優化方法。
上述簡單搭建的卷積網路同樣可以生成完全可執行的程式碼,這樣可以避免大量的一般程式碼問題與重複性工作。
import tensorflow as tfimport pandas as pdtf.logging.set_verbosity(tf.logging.INFO)project_name="CNN"train_csv_file=""test_csv_file=""image_resize=[28,28]def model_fn(features, labels, mode, params): convolutional_2d_1 = tf.layers.conv2d( inputs=features, filters=32, kernel_size=[3,3], strides=(1,1), padding="same", data_format="channels_last", dilation_rate=(1,1), activation=tf.nn.relu, use_bias=True) max_pool_2d_1 = tf.layers.max_pooling2d( inputs=convolutional_2d_1, pool_size=[2,2], strides=[2,2], padding=`same`, data_format=`channels_last`) convolutional_2d_2 = tf.layers.conv2d( inputs=max_pool_2d_1, filters=64, kernel_size=[3,3], strides=(1,1), padding="same", data_format="channels_last", dilation_rate=(1,1), activation=tf.nn.relu, use_bias=True) max_pool_2d_2 = tf.layers.max_pooling2d( inputs=max_pool_2d_1, pool_size=[2,2], strides=[2,2], padding=`same`, data_format=`channels_last`) convolutional_2d_3 = tf.layers.conv2d( inputs=max_pool_2d_2, filters=128, kernel_size=[3,3], strides=(1,1), padding="same", data_format="channels_last", dilation_rate=(1,1), activation=tf.nn.relu, use_bias=True) max_pool_2d_3 = tf.layers.max_pooling2d( inputs=convolutional_2d_3, pool_size=[2,2], strides=[2,2], padding=`same`, data_format=`channels_last`) flatten_1 = tf.reshape(max_pool_2d_3, [-1, 2048]) dense_1 = tf.layers.dense(inputs=flatten_1, units=1024, activation=tf.nn.relu) dropout_1= tf.layers.dropout(inputs=dense_1, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN) dense_2 = tf.layers.dense(inputs=dropout_1, units=256, activation=tf.nn.relu) logits=dense_2 predictions = { "classes": tf.argmax(input=logits, axis=1), "probabilities": tf.nn.softmax(logits, name="softmax_tensor") } #Prediction and training if mode == tf.estimator.ModeKeys.PREDICT: return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions) # Calculate Loss (for both TRAIN and EVAL modes) onehot_labels = tf.one_hot(indices=tf.cast(labels, tf.int32), depth=256) loss = tf.losses.softmax_cross_entropy( onehot_labels=onehot_labels, logits=logits) # Compute evaluation metrics. accuracy = tf.metrics.accuracy(labels=labels, predictions=predictions["classes"], name=`acc_op`) metrics = {`accuracy`: accuracy} tf.summary.scalar(`accuracy`, accuracy[1]) # Configure the Training Op (for TRAIN mode) if mode == tf.estimator.ModeKeys.TRAIN: optimizer = tf.train.AdagradOptimizer(learning_rate=0.001) train_op = optimizer.minimize( loss=loss, global_step=tf.train.get_global_step()) return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op) # Add evaluation metrics (for EVAL mode) eval_metric_ops = { "accuracy": tf.metrics.accuracy( labels=labels, predictions=predictions["classes"])} return tf.estimator.EstimatorSpec( mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)# Parse CSV input file and resize imagedef _parse_csv(line): parsed_line= tf.decode_csv(line, [[""], []]) filename = parsed_line[0] label = parsed_line[1] image_string = tf.read_file(filename) image_decoded = tf.image.decode_jpeg(image_string, channels=3) image_resized = tf.image.resize_images(image_decoded, image_resize) image_gray = tf.image.rgb_to_grayscale(image_resized) return image_gray, labeldef data_train_estimator(): dataset = tf.data.TextLineDataset(train_csv_file).map(_parse_csv) # Map each line to convert the data dataset = dataset.batch(100) dataset = dataset.shuffle(1000) dataset = dataset.repeat() iterator = dataset.make_one_shot_iterator() # create one shot iterator feature, label = iterator.get_next() return feature, labeldef data_test_estimator(): dataset = tf.data.TextLineDataset(test_csv_file).map(_parse_csv) # Map each line to convert the data dataset = dataset.batch(100) iterator = dataset.make_one_shot_iterator() # create one shot iterator feature, label = iterator.get_next() return feature, labeldef main(unused_argv): # MAIN ENTRY # Create the Estimator classifier = tf.estimator.Estimator( model_fn=model_fn, model_dir="/tmp/"+project_name, params={ # PARAMS } ) classifier.train(input_fn=data_train_estimator, steps=30000) eval_results = classifier.evaluate(input_fn=data_test_estimator) tf.summary.scalar("Accuracy", eval_results["accuracy"]) print(eval_results)if __name__ == "__main__": tf.app.run()複製程式碼
TensorEditor 主要有以下特點:
-
易於使用:我們只需要新增模組、連線模組並在最後加入評估模組,就能完成搭建。
-
由易到難:只需要疊加不同的模組,我們就能建立如 VGG 那樣的複雜深度網路。
-
引數直觀:可以輕鬆修改各結點的配置與引數,從而搭建定製化的深度網路。
-
生成程式碼:搭建完深度架構,我們就能直接生成可執行的 TensorFlow 程式碼(Python 2.7)。
90 秒的 MNIST 教程
在上面的視訊中,開發者展示瞭如何使用 TensorEditor 在 90 秒內快速搭建一個可用於 MNIST 手寫數字識別的簡單網路。對於 TensorEditor 這種構建序貫 CNN 模型的簡單工具,我們只需要準備兩件事就能開始搭建模型模型:
-
下載 MNIST 手寫資料集:https://github.com/damiles/TensorEditor_SampleData/raw/master/mnist_png.tar.gz
-
確定網路架構:https://www.tensorflow.org/tutorials/layers#building_the_cnn_mnist_classifier
TensorEditor 接受 CSV 格式的特徵資料集或具有 CSV 標籤的影像資料集作為資料輸入,並且需要訓練和測試/評估兩個 CSV 檔案。當我們從上面的連結下載資料集並提取影像資料時,我們會有兩個 CSV 檔案和兩個包含所有影像的資料夾(測試和訓練)。
現在我們就可以在 TensorEditor 中建立將要用於手寫數字識別的卷積網路架構,下面展示的架構和 TensorFlow 文件中保持一致。
-
卷積層 1:使用 32 個 5×5 大小的卷積核和 ReLU 啟用函式
-
池化層 1:使用 2×2 濾波器和步幅為 2 的最大池化運算(池化區域不重疊)
-
卷積層 2:使用 64 個 5×5 大小的卷積核和 ReLU 啟用函式
-
池化層 2:同樣使用 2×2 濾波器和步幅為 2 的最大池化運算
-
全連線層 1:1024 個神經元,Dropout 正則化率為 0.4
-
分類層:10 個神經元,每個神經元表示 0 到 9 這十個數字。
我們只需要按步驟先新增一個輸入 csv 資料集模組,並設定 train.csv 和 test.csv 的地址。然後依次新增上述的卷積和全連線等模組,並設定好對應的引數,如卷積核大小、卷積核數量和啟用函式等。最後主需要新增 Estimator 模組,並設定損失函式、最優化方法和學習率等配置就能完成架構上的搭建。如下所示為使用視覺化方法搭建的架構:
最後上面的網路就能生成對應的程式碼,我們可直接複製到原生程式碼編輯器中並執行:
本文為機器之心整理,轉載請聯絡本公眾號獲得授權。