【TensorFlow-windows】学习笔记三——实战准备
前言
因?yàn)閷W(xué)習(xí)TensorFlow的內(nèi)容較多,如果只看API會(huì)很無聊,可以結(jié)合實(shí)例去學(xué)習(xí)。但是在構(gòu)建基本的模型之前,需要學(xué)一些準(zhǔn)備知識:數(shù)據(jù)讀取、預(yù)處理、優(yōu)化器、損失函數(shù)
國際慣例,參考網(wǎng)址:
TensorFlow中文社區(qū)
TensorFlow官方文檔
如何選擇優(yōu)化器 optimizer
TensorFlow-Examples
TensorFlow中的Neural Network
TensorFlow中的Train
深入淺出Tensorflow(三):訓(xùn)練神經(jīng)網(wǎng)絡(luò)模型的常用方法
理解tf.train.slice_input_producer()和tf.train.batch()
此外,為了模擬現(xiàn)實(shí)數(shù)據(jù)集,這里將mnist手寫數(shù)字?jǐn)?shù)據(jù)集轉(zhuǎn)換成圖片格式存儲(chǔ),放一下網(wǎng)盤鏈接:鏈接:https://pan.baidu.com/s/1ugEy85182vjcXQ8VoMJAbg 密碼:1o83
處理數(shù)據(jù)集
從文本文件讀取圖像數(shù)據(jù)
按照caffe的讀取習(xí)慣,把圖片的路徑和標(biāo)簽全部用txt文本文件存儲(chǔ)起來,即路徑\圖片名 標(biāo)簽的格式:
./mnist/train/5/5_1.png 5 ./mnist/train/0/0_2.png 0 ./mnist/train/4/4_3.png 4 ./mnist/train/1/1_4.png 1然后參考TensorFlow-Examples中的build_an_image_dataset 方法按照文本文件中存儲(chǔ)的路徑和標(biāo)簽去按行讀取
imagepaths, labels = list(), list() data = open(dataset_path, 'r').read().splitlines() for d in data:imagepaths.append(d.split(' ')[0])labels.append(int(d.split(' ')[1]))在TF中打亂數(shù)據(jù)以及分批
因?yàn)槲覀円胻ensorflow處理數(shù)據(jù),所以必須將這些文本轉(zhuǎn)換成tensorflow能處理的形式
# 轉(zhuǎn)換為張量 imagepaths = tf.convert_to_tensor(imagepaths, dtype=tf.string) labels = tf.convert_to_tensor(labels, dtype=tf.int32)打亂數(shù)據(jù)
# 建立TF隊(duì)列,打亂數(shù)據(jù) image, label = tf.train.slice_input_producer([imagepaths, labels],shuffle=True)這里看一下這個(gè)slice_input_producer函數(shù):
tf.train.slice_input_producer(tensor_list,num_epochs=None,shuffle=True,seed=None,capacity=32,shared_name=None,name=None )- 作用:為tensor_list中的每個(gè)Tensor建立切片
- 部分參數(shù):
tensor_list:Tensor形式的列表,第一個(gè)維度必須相同
num_epochs:每個(gè)切片創(chuàng)建多少次
shuffle:打亂順序
所以在打亂順序的時(shí)候?qū)⒋撕瘮?shù)的shuffle參數(shù)設(shè)置成True即可
圖片讀取和處理
打亂數(shù)據(jù)路徑以后,就可以讀取了,tensorflow也提供了圖像處理相關(guān)函數(shù),這里列部分有用的:
調(diào)整圖像亮度:
tf.image.adjust_brightness(image,delta )調(diào)整圖像對比度:
tf.image.adjust_contrast(images,contrast_factor )伽馬校正:
tf.image.adjust_gamma(image,gamma=1,gain=1 )從中間向邊緣裁剪圖像:
tf.image.central_crop(image,central_fraction )裁剪圖片,分別是左上角縱坐標(biāo)、橫坐標(biāo),裁剪的高度、寬度:
tf.image.crop_to_bounding_box(image,offset_height,offset_width,target_height,target_width )圖像解碼:將對應(yīng)圖像解碼為uint8張量(還有對應(yīng)編碼的encode函數(shù)):
- tf.image.decode_bmp
- tf.image.decode_gif
- tf.image.decode_image
- tf.image.decode_jpeg
- tf.image.decode_png
圖像翻轉(zhuǎn):
- tf.image.flip_left_right左右翻轉(zhuǎn)
- tf.image.flip_up_down上下翻轉(zhuǎn)
- tf.image.rot90翻轉(zhuǎn)90度,可自定義次數(shù)
- tf.image.transpose_image圖像轉(zhuǎn)置
圖像轉(zhuǎn)換:
- tf.image.grayscale_to_rgb:灰度圖轉(zhuǎn)換為RGB
- tf.image.hsv_to_rgb:HSV圖轉(zhuǎn)換為RGB
- tf.image.rgb_to_grayscale:RGB轉(zhuǎn)灰度圖
- tf.image.rgb_to_hsv:RGB轉(zhuǎn)HSV
- tf.image.rgb_to_yiq:RGB轉(zhuǎn)YIQ
- tf.image.rgb_to_yuv:RGB轉(zhuǎn)YUV
- tf.image.yiq_to_rgb:YIQ轉(zhuǎn)RGB
- tf.image.yuv_to_rgb:YUV轉(zhuǎn)RGB
圖像填充:
tf.image.pad_to_bounding_box(image,offset_height,offset_width,target_height,target_width )在圖像上面填充offset_height高度的0,在圖像左邊填充offset_width寬度的0,再按照最終目標(biāo)寬度和高度在下邊和右邊填充圖像。
圖像歸一化:tf.image.per_image_standardization(image)
圖像大小調(diào)整
tf.image.resize_images(images,size,method=ResizeMethod.BILINEAR,align_corners=False )其中插值方法有:
AREA BICUBIC BILINEAR NEAREST_NEIGHBOR所以在圖像預(yù)處理過程中,先按照路徑讀取圖像以及解碼,然后調(diào)整圖像大小,歸一化:
# 讀取數(shù)據(jù)image = tf.read_file(image) image = tf.image.decode_jpeg(image, channels=CHANNELS)# 將圖像resize成規(guī)定大小image = tf.image.resize_images(image, [IMG_HEIGHT, IMG_WIDTH])# 手動(dòng)歸一化image = image * 1.0/127.5 - 1.0
創(chuàng)建批量數(shù)據(jù)
就一個(gè)函數(shù):
tf.train.batch(tensors,batch_size,num_threads=1,capacity=32,enqueue_many=False,shapes=None,dynamic_pad=False,allow_smaller_final_batch=False,shared_name=None,name=None )- 作用:利用隊(duì)列的方法存儲(chǔ)批數(shù)據(jù)
- 部分參數(shù):
tensors:張量列表或者字典
batch_size:批大小
num_thread:并行入隊(duì),采用線程數(shù)
capacity:整數(shù),隊(duì)列里面最多有多少個(gè)元素
在制作數(shù)據(jù)集中,直接這樣:
# 創(chuàng)建batch X, Y = tf.train.batch([image, label], batch_size=batch_size,capacity=batch_size * 8,num_threads=4)具體可以參考這篇博客的描述:TensorFlow 組合訓(xùn)練數(shù)據(jù)(batching)、TensorFlow 筆記(九):數(shù)據(jù)讀取
TF中神經(jīng)網(wǎng)絡(luò)相關(guān)函數(shù)
這里需要注意的是tf.layers和tf.nn中均有相關(guān)層的實(shí)現(xiàn),它們之間的區(qū)別我也不太清楚,但是從網(wǎng)上的觀點(diǎn)來看,大部分人認(rèn)為前者是以后者作為后端的,具體分析可看:
tf.nn.conv2d vs tf.layers.conv2d
tensorflow學(xué)習(xí):tf.nn.conv2d 和 tf.layers.conv2d
Neural Network
層相關(guān)
目前構(gòu)建神經(jīng)網(wǎng)絡(luò)還是使用前者的吧:
average_pooling1d(...): 一維輸入平均池化 average_pooling2d(...): 二維輸入平均池化(比如圖像) average_pooling3d(...): 三維輸入平均池化(比如立體) batch_normalization(...): 批歸一化 conv1d(...): 一維卷積 conv2d(...): 二維卷積 conv2d_transpose(...): 2D反卷積 conv3d(...): 三維卷積 conv3d_transpose(...): 三維轉(zhuǎn)置卷積 dense(...): 全連接 dropout(...): 隨機(jī)丟失神經(jīng)元 flatten(...): 保存第一個(gè)維度去展平數(shù)據(jù) max_pooling1d(...): 一維輸入最大池化 max_pooling2d(...): 二維輸入最大池化 max_pooling3d(...): 三維輸入最大池化 separable_conv1d(...): 按照深度獨(dú)立方法一維卷積 separable_conv2d(...): 按照深度獨(dú)立方法二維卷積激活函數(shù)和損失相關(guān)
而tf.nn也不是完全沒用,它存儲(chǔ)了激活函數(shù)以及部分損失函數(shù):
sigmoid(...): sigmoid激活函數(shù) tanh(...): tanh激活函數(shù) softplus(...): 激活函數(shù) log(exp(features) + 1). relu(...): ReLU激活函數(shù) leaky_relu(...): Leaky ReLU 激活函數(shù)max(features,leak*features) elu(...): ELU激活函數(shù):features if features>0 else alpha*(e^features-1) selu(...): scaled exponential linear: scale * alpha * (exp(features) - 1) crelu(...): 關(guān)聯(lián)ReLU激活函數(shù) relu6(...): Rectified Linear 6: min(max(features, 0), 6). softmax(...): softmax 激活函數(shù)(一般用于最后一層) softsign(...): 激活函數(shù) features / (abs(features) + 1). dropout(...):神經(jīng)元抑制ctc_loss(...): CTC (Connectionist Temporal Classification)損失 nce_loss(...):計(jì)算noise-contrastive estimation訓(xùn)練損失 l2_loss(...): L2 損失. log_poisson_loss(...): log Poisson損失. weighted_cross_entropy_with_logits(...): 加權(quán)交叉熵?fù)p失(默認(rèn)已將features用softmax激活) sparse_softmax_cross_entropy_with_logits(...): 計(jì)算logits 和 labels的稀疏交叉熵?fù)p失 softmax_cross_entropy_with_logits(...): 計(jì)算logits 和 labels的交叉熵?fù)p失(默認(rèn)已將features用softmax激活) softmax_cross_entropy_with_logits_v2(...): 計(jì)算logits 和 labels的交叉熵?fù)p失(默認(rèn)已將features用softmax激活) sigmoid_cross_entropy_with_logits(...): 經(jīng)sigmoid 函數(shù)激活之后的交叉熵(默認(rèn)已將features用softmax激活)moments(...): 計(jì)算輸入數(shù)據(jù)的均值和方差. normalize_moments(...): 基于sufficient statistics計(jì)算輸入數(shù)據(jù)的均值和方差top_k(...): 返回最后一個(gè)維度的k個(gè)最大值和索引 in_top_k(...):查詢目標(biāo)值是否在k個(gè)預(yù)測值中 xw_plus_b(...): 計(jì)算 matmul(x, weights) + biases. relu_layer(...): 計(jì)算 Relu(x * weight + biases).這里幾個(gè)地方需要注意:
正則項(xiàng)
兩種正則化方法,三種函數(shù):
一范式正則化:
tf.contrib.layers.l1_regularizer(scale,scope=None )二范式正則化:
tf.contrib.layers.l2_regularizer(scale,scope=None )兩種范式一起用
tf.contrib.layers.l1_l2_regularizer(scale_l1=1.0,scale_l2=1.0,scope=None )
最后要將正則化應(yīng)用到權(quán)重中:
tf.contrib.layers.apply_regularization(regularizer,weights_list=None )TF中的訓(xùn)練方法
包含優(yōu)化器、梯度計(jì)算、梯度裁剪、學(xué)習(xí)率及其衰減,參考這里
優(yōu)化器
Optimizer GradientDescentOptimizer AdadeltaOptimizer AdagradOptimizer AdagradDAOptimizer MomentumOptimizer AdamOptimizer FtrlOptimizer ProximalGradientDescentOptimizer ProximalAdagradOptimizer RMSPropOptimizer各種梯度優(yōu)化器,注意他們是屬于類,對應(yīng)有很多函數(shù)可調(diào)用,比如minimize
梯度計(jì)算
gradients AggregationMethod stop_gradient hessians梯度裁剪
clip_by_value clip_by_norm clip_by_average_norm clip_by_global_norm global_norm學(xué)習(xí)率及其衰減
exponential_decay inverse_time_decay natural_exp_decay piecewise_constant polynomial_decay cosine_decay linear_cosine_decay noisy_linear_cosine_decay一般不用搞那么復(fù)雜,隨便用兩個(gè)就行:
指數(shù)形式的衰減方法
tf.train.exponential_decay(learning_rate,#初始學(xué)習(xí)率global_step,#非負(fù),衰減指數(shù)decay_steps,#正數(shù),衰減周期decay_rate,#衰減率staircase=False,#如果是True,就是離散形式的衰減name=None ) ''' decayed_learning_rate = learning_rate *decay_rate ^ (global_step / decay_steps) staircase是True的時(shí)候(global_step / decay_steps)轉(zhuǎn)換為整數(shù) '''多項(xiàng)式衰減:
tf.train.polynomial_decay(learning_rate,global_step,decay_steps,end_learning_rate=0.0001,power=1.0,cycle=False,name=None )其中的cycle參數(shù)是決定lr是否在下降后重新上升的過程。cycle參數(shù)的初衷是為了防止網(wǎng)絡(luò)后期lr十分小導(dǎo)致一直在某個(gè)局部最小值中振蕩,突然調(diào)大lr可以跳出注定不會(huì)繼續(xù)增長的區(qū)域探索其他區(qū)域。
沒cycle時(shí)的計(jì)算方法:
global_step = min(global_step, decay_steps) decayed_learning_rate = (learning_rate - end_learning_rate) *(1 - global_step / decay_steps) ^ (power) +end_learning_rate有cycle時(shí)的計(jì)算方法:
decay_steps = decay_steps * ceil(global_step / decay_steps) decayed_learning_rate = (learning_rate - end_learning_rate) *(1 - global_step / decay_steps) ^ (power) +end_learning_rate
一般使用流程
一般是先定義學(xué)習(xí)率,然后使用優(yōu)化器最小化損失
比如使用指數(shù)衰減:
... global_step = tf.Variable(0, trainable=False) starter_learning_rate = 0.1 learning_rate = tf.train.exponential_decay(starter_learning_rate, global_step,100000, 0.96, staircase=True) # Passing global_step to minimize() will increment it at each step. learning_step = (tf.train.GradientDescentOptimizer(learning_rate).minimize(...my loss..., global_step=global_step) )比如使用多項(xiàng)式衰減
... global_step = tf.Variable(0, trainable=False) starter_learning_rate = 0.1 end_learning_rate = 0.01 decay_steps = 10000 learning_rate = tf.train.polynomial_decay(starter_learning_rate, global_step,decay_steps, end_learning_rate,power=0.5) # Passing global_step to minimize() will increment it at each step. learning_step = (tf.train.GradientDescentOptimizer(learning_rate).minimize(...my loss..., global_step=global_step) )這個(gè)global_step隨著訓(xùn)練自增,具體可以看這里
用這段代碼可以看出來:
import tensorflow as tf; import numpy as np; import matplotlib.pyplot as plt; x = tf.placeholder(tf.float32, shape=[None, 1], name='x') y = tf.placeholder(tf.float32, shape=[None, 1], name='y') w = tf.Variable(tf.constant(0.0))global_steps = tf.Variable(0, trainable=False) learning_rate = tf.train.exponential_decay(0.1, global_steps, 10, 2, staircase=False) loss = tf.pow(w*x-y, 2)train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_steps)with tf.Session() as sess:sess.run(tf.initialize_all_variables())for i in range(10):sess.run(train_step, feed_dict={x:np.linspace(1,2,10).reshape([10,1]),y:np.linspace(1,2,10).reshape([10,1])})print (sess.run(global_steps))注意,經(jīng)常無需人工計(jì)算梯度然后apply到相關(guān)參數(shù)列表上,因?yàn)閙inimize已經(jīng)包含這兩步驟了。
簡單例子
按照這個(gè)例子很容易利用CNN實(shí)現(xiàn)一個(gè)手寫數(shù)字識別網(wǎng)絡(luò)
先引入相關(guān)包以及定義數(shù)據(jù)相關(guān)信息
然后按照標(biāo)簽中定義的圖片路徑和標(biāo)簽,制作數(shù)據(jù)集:
def read_images(dataset_path, batch_size):imagepaths, labels = list(), list()data = open(dataset_path, 'r').read().splitlines()for d in data:imagepaths.append(d.split(' ')[0])labels.append(int(d.split(' ')[1]))# 轉(zhuǎn)換為張量imagepaths = tf.convert_to_tensor(imagepaths, dtype=tf.string)labels = tf.convert_to_tensor(labels, dtype=tf.int32)# 建立TF隊(duì)列,打亂數(shù)據(jù)image, label = tf.train.slice_input_producer([imagepaths, labels],shuffle=True)# 讀取數(shù)據(jù)image = tf.read_file(image)image = tf.image.decode_jpeg(image, channels=CHANNELS)# 將圖像resize成規(guī)定大小image = tf.image.resize_images(image, [IMG_HEIGHT, IMG_WIDTH])# 手動(dòng)歸一化image = image * 1.0/127.5 - 1.0# 創(chuàng)建batchX, Y = tf.train.batch([image, label], batch_size=batch_size,capacity=batch_size * 8,num_threads=4)return X, Y設(shè)置網(wǎng)絡(luò)參數(shù)
#網(wǎng)絡(luò)參數(shù) learning_rate = 0.001#學(xué)習(xí)率 num_steps = 100#迭代次數(shù) batch_size = 128#每批大小 display_step = 100#顯示調(diào)試信息 dropout = 0.75 # dropout保留比率 X, Y = read_images(DATASET_PATH, batch_size)#讀取數(shù)據(jù)集定義網(wǎng)絡(luò)結(jié)構(gòu):
# 創(chuàng)建卷積模型 def conv_net(x, n_classes, dropout, reuse, is_training):# Define a scope for reusing the variableswith tf.variable_scope('ConvNet', reuse=reuse):# 第一層卷積conv1 = tf.layers.conv2d(x, 32, 5, activation=tf.nn.relu)# 最大池化conv1 = tf.layers.max_pooling2d(conv1, 2, 2)# 第二層卷積conv2 = tf.layers.conv2d(conv1, 64, 3, activation=tf.nn.relu)# 最大池化conv2 = tf.layers.max_pooling2d(conv2, 2, 2)# 拉成一維向量fc1 = tf.layers.flatten(conv2)# 全連接層fc1 = tf.layers.dense(fc1, 1024)# 應(yīng)用dropoutfc1 = tf.layers.dropout(fc1, rate=dropout, training=is_training)# 輸出out = tf.layers.dense(fc1, n_classes)# softmax輸出out = tf.nn.softmax(out) if not is_training else outreturn out定義訓(xùn)練網(wǎng)絡(luò)和評估網(wǎng)絡(luò),并進(jìn)行訓(xùn)練
#訓(xùn)練網(wǎng)絡(luò) logits_train = conv_net(X, N_CLASSES, dropout, reuse=False, is_training=True) # 測試網(wǎng)絡(luò) logits_test = conv_net(X, N_CLASSES, dropout, reuse=True, is_training=False)# 定義損失和優(yōu)化器 loss_op = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits_train, labels=Y)) optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate) train_op = optimizer.minimize(loss_op)# 評估模型 correct_pred = tf.equal(tf.argmax(logits_test, 1), tf.cast(Y, tf.int64)) accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))# 初始化變量 init = tf.global_variables_initializer()# 保存模型參數(shù) saver = tf.train.Saver()# 開始訓(xùn)練 with tf.Session() as sess:coord=tf.train.Coordinator()# 初始化參數(shù)sess.run(init)# 數(shù)據(jù)集隊(duì)列tf.train.start_queue_runners(sess=sess,coord=coord)# 循環(huán)訓(xùn)練for step in range(1, num_steps+1):if step % display_step == 0:# Run optimization and calculate batch loss and accuracy_, loss, acc = sess.run([train_op, loss_op, accuracy])print("Step " + str(step) + ", Minibatch Loss= " + \"{:.4f}".format(loss) + ", Training Accuracy= " + \"{:.3f}".format(acc))else: sess.run(train_op)coord.request_stop()#請求線程結(jié)束coord.join()#等待線程結(jié)束print("Optimization Finished!")# 保存模型saver.save(sess, './cnn_mnist_model/my_tf_model')結(jié)果
Step 100, Minibatch Loss= 0.1098, Training Accuracy= 0.969 Step 200, Minibatch Loss= 0.1070, Training Accuracy= 0.969 Step 300, Minibatch Loss= 0.0393, Training Accuracy= 1.000 Step 400, Minibatch Loss= 0.0688, Training Accuracy= 0.984 Step 500, Minibatch Loss= 0.0559, Training Accuracy= 0.992 Step 600, Minibatch Loss= 0.0433, Training Accuracy= 0.984 Step 700, Minibatch Loss= 0.0341, Training Accuracy= 0.992 Step 800, Minibatch Loss= 0.0309, Training Accuracy= 0.984 Step 900, Minibatch Loss= 0.0825, Training Accuracy= 0.969 Step 1000, Minibatch Loss= 0.0211, Training Accuracy= 1.000 Optimization Finished!個(gè)人感覺相對于theano使用tensorflow的好處在于,無需自己寫梯度優(yōu)化了,創(chuàng)建模型貌似不用自己去挨個(gè)權(quán)重定義和初始化,這里就沒針對每個(gè)卷積核定義變量和單獨(dú)初始化,除此之外,沒感覺有啥其它便利性了。
還有一個(gè)重要問題是,這個(gè)模型保存了以后,好像無法拿過來單獨(dú)測試一張圖片,因?yàn)檫@里沒有函數(shù)提供額外輸入,即使想調(diào)用logits_test來測試單張圖片,也不好弄,因?yàn)閄無法在重載模型后指定單張圖片,所以還得改代碼,后續(xù)再研究研究模型保存與載入。
后記
這一部分主要了解一下在TensorFlow中構(gòu)建神經(jīng)網(wǎng)絡(luò)可以使用的部分函數(shù)。
我嘞個(gè)乖乖,感覺好難啊,跟Theano差不多,好底層,想脫坑轉(zhuǎn)TensorLayer或者TFLearn這兩個(gè)基于tensorflow的二次封裝庫,知乎上有對應(yīng)討論如何比較Keras, TensorLayer, TFLearn ?,貌似大部分人都推薦TL,先繼續(xù)折騰TensorFlow的保存和加載模型,如果實(shí)在不行,后續(xù)去了解一下對工程實(shí)現(xiàn)的支持程度以及模型的保存和載入難度,再選擇框架。
總結(jié)
以上是生活随笔為你收集整理的【TensorFlow-windows】学习笔记三——实战准备的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【TensorFlow-windows】
- 下一篇: java信息管理系统总结_java实现科