LeNet-5模型的Python實現
來自專欄深度學習+自然語言處理(NLP)
LeNet-5模型的Python實現
本文基於Python的Tensorflow庫實現了經典模型LeNet-5,並在數據集CIFAR-10上進行訓練和測試。本文的代碼均經過實測,讀者也可以在我的Github下載Jupyter Notebook文件.LeNet-5模型- python 版本: Python 3.5.4
- tensorflow 版本:tensorflow 1.1.0
def normalize(x): """ 歸一化至範圍[0, 1] x: 像素數據列表 return: 歸一化後的數據 """ return x/255 import numpy as npnormalize(np.array([120,329,255])) #測試
def one_hot_encode(x): """ one-hot編碼. : x: 標籤列表 : return: Numpy array格式的one-hot編碼標籤列表 """ output = np.zeros((len(x),10)) # 根據輸入數組的長度和類別數量創建數組 for i in range(len(x)): output[i][x[i]] = 1 # 將數組的對應位置置為1 return outputone_hot_encode(np.array([1,3,6,2,4,9])) #測試
# 這裡需要下載helper.py,並保存在工作目錄下,下載鏈接在「目標」章節import helperhelper.preprocess_and_save_data(cifar-10-batches-py, normalize, one_hot_encode)import pickle# 讀取保存的數據valid_features, valid_labels = pickle.load(open(preprocess_validation.p, mode=rb))
import tensorflow as tfdef neural_net_image_input(image_shape): """ 返回輸入圖像的tensor : image_shape: 圖像的尺寸 : return: 正確尺寸的Tensor """ return tf.placeholder(tf.float32, [None, image_shape[0], image_shape[1], image_shape[2]], name = x)neural_net_image_input([32, 32, 3]) #測試
def neural_net_label_input(n_classes): """ 返回輸入標籤的tensor : n_classes: 標籤類別數量 : return: 正確尺寸的Tensor """ return tf.placeholder(tf.float32, [None, n_classes], name = y)neural_net_label_input(10) #測試
def neural_net_keep_prob_input(): """ 返回tensor格式的概率,該概率是drop out演算法的參數,表示保存的神經元的比例 """ return tf.placeholder(tf.float32, None, name = keep_prob)
def conv2d_avgpool(x_tensor, conv_num_outputs, conv_ksize, conv_strides, pool_ksize, pool_strides, keep_prob): """ 對輸入x_tensor應用卷積層和池化層 x_tensor: TensorFlow Tensor conv_num_outputs: 卷積層的輸出數量 conv_ksize: 卷積核的尺寸 conv_strides: 卷積的步進 pool_ksize: 池化層的核尺寸 pool_strides: 池化層的步進 keep_prob: dropout保存率 : return: 經過卷積層和池化層後的tensor """ weight = tf.Variable(tf.random_normal([conv_ksize[0], conv_ksize[1], x_tensor.get_shape().as_list()[3],conv_num_outputs])) bias = tf.Variable(tf.random_normal([conv_num_outputs])) x = tf.nn.conv2d(x_tensor, weight, strides= [1,conv_strides[0],conv_strides[1],1], padding = VALID) x = tf.nn.bias_add(x, bias) x = tf.nn.dropout(x, keep_prob) x = tf.nn.avg_pool(x, ksize=[1, pool_ksize[0], pool_ksize[1], 1], strides=[1, pool_strides[0], pool_strides[1], 1], padding=SAME) x = tf.nn.sigmoid(x) return xconv2d_avg_pool(tf.placeholder(tf.float32, [None, 32,32,3]), 6, (5,5), (1,1), (2,2), (2,2), 0.8) # 測試
import tensorflow.contrib as tfcdef flatten(x_tensor): """ 將x_tensor轉換為(批大小, flatten後圖像大小) x_tensor: 輸入tensor return: 輸出tensor """ return tfc.layers.flatten(x_tensor)flatten(tf.placeholder(tf.float32, [None, 16,16,10])) #測試
全連接層
全連接層相當於常規神經網路中的隱藏層,該層的唯一參數是輸出尺寸(即神經元的數量)。def fully_conn(x_tensor, num_outputs): """ 定義全連接層 : x_tensor: 輸入tensor : num_outputs: 輸出尺寸 : return: tensor """ return tfc.layers.fully_connected(x_tensor, num_outputs)fully_conn(tf.placeholder(tf.float32, [None, 2560]), 120) #測試
def output(x_tensor, num_outputs): """ 定義輸出層 : x_tensor: 輸入tensor : num_outputs: 輸出尺寸 : return: tensor """ return tfc.layers.fully_connected(inputs = x_tensor, num_outputs = num_outputs, activation_fn=None)In [197]:output(tf.placeholder(tf.float32, [None, 120]), 10) #測試
有了上述模塊,接下來可以搭積木式搭建LeNet-5模型,為了方便,我們將該模型的結構圖放在這裡:
def LeNet(x, keep_prob): """ 打造LeNet : x: 輸入tensor : keep_prob: dropout的保存率 : return: Tensor """ # C1 and S2 layer x = conv2d_avgpool(x, 6, (5,5), (1,1), (2,2), (2,2), keep_prob) # C3 and S4 layer x = conv2d_avgpool(x, 16, (5,5), (1,1), (2,2), (2,2), keep_prob) # C5 layer weight = tf.Variable(tf.random_normal([5, 5, x.get_shape().as_list()[3],120])) bias = tf.Variable(tf.random_normal([120])) x = tf.nn.conv2d(x, weight, strides= [1,5,5,1], padding = VALID) x = tf.nn.bias_add(x, bias) x = flatten(x) # F6 layer x= fully_conn(x, 84) # ouput layer x = output(x, 10) return x
tf.reset_default_graph()# 輸入x = neural_net_image_input((32, 32, 3))y = neural_net_label_input(10)keep_prob = neural_net_keep_prob_input()# 模型logits = LeNet(x, keep_prob)# Name logits Tensor, so that is can be loaded from disk after traininglogits = tf.identity(logits, name=logits)# 損失函數和優化器cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y))optimizer = tf.train.AdamOptimizer().minimize(cost)# 使用準確率作為meritccorrect_pred = tf.equal(tf.argmax(logits, 1), tf.argmax(y, 1))accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32), name=accuracy)
def train_neural_network(session, optimizer, keep_probability, feature_batch, label_batch): """ 對批次訓練集進行訓練 : session: TensorFlow session : optimizer: 優化器 : keep_probability: dropout參數 : feature_batch: 特徵批次 : label_batch: 標籤批次 """ session.run(optimizer, feed_dict={x: feature_batch, y: label_batch, keep_prob: keep_probability}) pass
def print_stats(session, feature_batch, label_batch, cost, accuracy): """ 列印損失函數和準確率 : session: TensorFlow session : feature_batch: 特徵批次 : label_batch: 標籤批次 : cost: 損失函數 : accuracy: 精確度 """ loss = session.run(cost, feed_dict={x: feature_batch, y: label_batch, keep_prob: 1.}) valid_acc = sess.run(accuracy, feed_dict={x: valid_features, y: valid_labels, keep_prob: 1.}) print(loss) print(valid_acc) pass
epochs = 30batch_size = 128keep_probability = 0.9save_model_path = ./image_classificationprint(Training...)with tf.Session() as sess: # Initializing the variables sess.run(tf.global_variables_initializer()) # Training cycle for epoch in range(epochs): # Loop over all batches n_batches = 5 for batch_i in range(1, n_batches + 1): for batch_features, batch_labels in helper.load_preprocess_training_batch(batch_i, batch_size): train_neural_network(sess, optimizer, keep_probability, batch_features, batch_labels) print(Epoch {:>2}, CIFAR-10 Batch {}: .format(epoch + 1, batch_i), end=) print_stats(sess, batch_features, batch_labels, cost, accuracy) # Save Model saver = tf.train.Saver() save_path = saver.save(sess, save_model_path)
%matplotlib inline%config InlineBackend.figure_format = retinaimport tensorflow as tfimport pickleimport helperimport randomtry: if batch_size: passexcept NameError: batch_size = 64save_model_path = ./image_classificationn_samples = 4top_n_predictions = 3def test_model(): test_features, test_labels = pickle.load(open(preprocess_training.p, mode=rb)) loaded_graph = tf.Graph() with tf.Session(graph=loaded_graph) as sess: # Load model loader = tf.train.import_meta_graph(save_model_path + .meta) loader.restore(sess, save_model_path) # Get Tensors from loaded model loaded_x = loaded_graph.get_tensor_by_name(x:0) loaded_y = loaded_graph.get_tensor_by_name(y:0) loaded_keep_prob = loaded_graph.get_tensor_by_name(keep_prob:0) loaded_logits = loaded_graph.get_tensor_by_name(logits:0) loaded_acc = loaded_graph.get_tensor_by_name(accuracy:0) # Get accuracy in batches for memory limitations test_batch_acc_total = 0 test_batch_count = 0 for train_feature_batch, train_label_batch in helper.batch_features_labels(test_features, test_labels, batch_size): test_batch_acc_total += sess.run( loaded_acc, feed_dict={loaded_x: train_feature_batch, loaded_y: train_label_batch, loaded_keep_prob: 1.0}) test_batch_count += 1 print(Testing Accuracy: {}
.format(test_batch_acc_total/test_batch_count)) # Print Random Samples random_test_features, random_test_labels = tuple(zip(*random.sample(list(zip(test_features, test_labels)), n_samples))) random_test_predictions = sess.run( tf.nn.top_k(tf.nn.softmax(loaded_logits), top_n_predictions), feed_dict={loaded_x: random_test_features, loaded_y: random_test_labels, loaded_keep_prob: 1.0}) helper.display_image_predictions(random_test_features, random_test_labels, random_test_predictions)test_model()INFO:tensorflow:Restoring parameters from ./image_classificationTesting Accuracy: 0.49238528481012656
至此,感謝閱讀。
推薦閱讀:
※一文掌握 Python,從 Zero 到 Hero。
※開源項目精選:SIX——Python2和3的兼容性庫
※人工智慧學Python,千鋒Python學習知識資料分享
※廢話少說:Python 這麼牛逼的 6 個原因是?
※吃條python壓壓驚(1)-dictionary
TAG:Python | 機器學習 | 深度學習DeepLearning |