【TensorFlow-windows】学习笔记五——自编码器
前言
上一篇博客介紹的是構建簡單的CNN去識別手寫數字,這一篇博客折騰一下自編碼,理論很簡單,就是實現對輸入數據的重構,具體理論可以看我前面的【theano-windows】學習筆記十三——去噪自編碼器
國際慣例,參考博客:
當我們在談論 Deep Learning:AutoEncoder 及其相關模型
Autoencoders
訓練代碼實現
不說理論了,直接擼代碼,包含兩個隱層,因此網絡的結構為四層:
單元數為784784的輸入層→→單元數為256256的第一個隱層→→單元數為128128的第二個隱層→→單元數為784的重構輸出層
接下來按照老樣子構建整個訓練流程:
讀數據→→初始化相關參數→→定義接收數據的接口以便測試使用→→初始化權重和偏置→→定義基本模塊(編碼和解碼)→→構建模型(先編碼再解碼)→→定義預測函數、損失函數、優化器→→訓練
有幾點一定要注意:
- 一定要定義數據的輸入接口,不然后期無法拿模型做預測
- 一定要記得構建預測函數用于后期的測試階段使用,不要只記得定義損失函數
讀數據
注意初始化直接將所有像素除以255255,這與前面一篇博客不同
IMG_HEIGHT=28 IMG_WIDTH=28 CHANNELS=3 #讀取數據集 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]))imagepaths=tf.convert_to_tensor(imagepaths,dtype=tf.string)labels=tf.convert_to_tensor(labels,dtype=tf.int32)image,label=tf.train.slice_input_producer([imagepaths,labels],shuffle=True)image=tf.read_file(image)image=tf.image.decode_jpeg(image,channels=CHANNELS)image=tf.image.rgb_to_grayscale(image) image=tf.reshape(image,[IMG_HEIGHT*IMG_WIDTH])image=tf.cast(image,tf.float32)image = image / 255.0image=tf.convert_to_tensor(image)inputX,inputY=tf.train.batch([image,label],batch_size=batch_size,capacity=batch_size*8,num_threads=4)return inputX,inputY初始化相關參數
learning_rate=0.01#學習率 num_steps=30000#訓練次數 batch_size=256#每批數據大小 disp_step=1000#每迭代多少次顯示訓練日志 num_class=10#總類別 num_hidden1=256#第一層隱單元數 num_hidden2=128#第二層隱單元數 num_input=IMG_HEIGHT*IMG_WIDTH#輸入、輸出單元數定義數據接收接口
#定義輸入接口 X=tf.placeholder(tf.float32,[None,num_input],name='X')初始化權重和偏置
#權重 weights={'encoder_h1':tf.Variable(tf.random_normal([num_input,num_hidden1])),'encoder_h2':tf.Variable(tf.random_normal([num_hidden1,num_hidden2])),'decoder_h1':tf.Variable(tf.random_normal([num_hidden2,num_hidden1])),'decoder_h2':tf.Variable(tf.random_normal([num_hidden1,num_input])) } #偏置 biases={'encoder_b1':tf.Variable(tf.random_normal([num_hidden1])),'encoder_b2':tf.Variable(tf.random_normal([num_hidden2])),'decoder_b1':tf.Variable(tf.random_normal([num_hidden1])),'decoder_b2':tf.Variable(tf.random_normal([num_input])) }定義基本模塊
#編碼器 def encoder(x):layer1=tf.nn.sigmoid(tf.add(tf.matmul(x,weights['encoder_h1']),biases['encoder_b1']))layer2=tf.nn.sigmoid(tf.add(tf.matmul(layer1,weights['encoder_h2']),biases['encoder_b2']))return layer2 def decoder(x):layer1=tf.nn.sigmoid(tf.add(tf.matmul(x,weights['decoder_h1']),biases['decoder_b1']))layer2=tf.nn.sigmoid(tf.add(tf.matmul(layer1,weights['decoder_h2']),biases['decoder_b2']))return layer2構建模型
#構建模型 encoder_op=encoder(X) decoder_op=decoder(encoder_op)定義預測函數、損失函數、優化器
#預測函數 y_pred=decoder_op y_true=X tf.add_to_collection('recon',y_pred) #定義損失函數和優化器 loss_op=tf.reduce_mean(tf.pow(y_true-y_pred,2)) optimizer=tf.train.RMSPropOptimizer(learning_rate=learning_rate).minimize(loss_op)開始訓練模型并保存結果
記得先初始化所有變量
#參數初始化 init=tf.global_variables_initializer() input_image,input_label=read_images('./mnist/train_labels.txt',batch_size)然后就可以訓練了,每次從隊列中取數據
#開始訓練和保存模型 saver=tf.train.Saver() with tf.Session() as sess:sess.run(init)coord=tf.train.Coordinator()tf.train.start_queue_runners(sess=sess,coord=coord)for step in range(1,num_steps+1):batch_x,batch_y=sess.run([input_image,tf.one_hot(input_label,num_class,1,0)])sess.run(optimizer,feed_dict={X:batch_x})if step%disp_step==0 or step==1:loss=sess.run(loss_op,feed_dict={X:batch_x })print('step '+str(step)+' ,loss '+'{:.4f}'.format(loss))coord.request_stop()coord.join()print('optimization finished')saver.save(sess,'./AE_mnist_model/AE_mnist')訓練結果:
step 1 ,loss 0.4566 step 1000 ,loss 0.1465 step 2000 ,loss 0.1291 step 3000 ,loss 0.1206 step 4000 ,loss 0.1158 step 5000 ,loss 0.1110 step 6000 ,loss 0.1081 step 7000 ,loss 0.1052 step 8000 ,loss 0.1039 step 9000 ,loss 0.1024 step 10000 ,loss 0.0969 step 11000 ,loss 0.0934 step 12000 ,loss 0.0934 step 13000 ,loss 0.0932 step 14000 ,loss 0.0872 step 15000 ,loss 0.0840 step 16000 ,loss 0.0832 step 17000 ,loss 0.0843 step 18000 ,loss 0.0830 step 19000 ,loss 0.0821 step 20000 ,loss 0.0813 step 21000 ,loss 0.0800 step 22000 ,loss 0.0776 step 23000 ,loss 0.0771 step 24000 ,loss 0.0754 step 25000 ,loss 0.0727 step 26000 ,loss 0.0735 step 27000 ,loss 0.0754 step 28000 ,loss 0.0739 step 29000 ,loss 0.0737 step 30000 ,loss 0.0727 optimization finished再貼一下使用上一篇博客的歸一化方法得到的訓練結果:
step 1 ,loss 2.1006 step 1000 ,loss 1.0853 step 2000 ,loss 1.0303 step 3000 ,loss 1.0057 step 4000 ,loss 0.9976 step 5000 ,loss 0.9814 step 6000 ,loss 0.9748 step 7000 ,loss 0.9687 step 8000 ,loss 0.9689 step 9000 ,loss 0.9576 step 10000 ,loss 0.9588 step 11000 ,loss 0.9571 step 12000 ,loss 0.9517 step 13000 ,loss 0.9495 step 14000 ,loss 0.9484 step 15000 ,loss 0.9432 step 16000 ,loss 0.9426 step 17000 ,loss 0.9378 step 18000 ,loss 0.9355 step 19000 ,loss 0.9347 step 20000 ,loss 0.9343 step 21000 ,loss 0.9322 step 22000 ,loss 0.9266 step 23000 ,loss 0.9267 step 24000 ,loss 0.9273 step 25000 ,loss 0.9269 step 26000 ,loss 0.9250 step 27000 ,loss 0.9257 step 28000 ,loss 0.9244 step 29000 ,loss 0.9199 step 30000 ,loss 0.9257 optimization finished很容易發現第二個模型收斂速度很慢,而且最后其實并未收斂到最優解,而且效果很差,相對于直接除以255255的處理方法,模型收斂就快很多,而且更傾向于收斂到了最優解 。所以數據預處理方式對結果影響也很大
測試代碼實現
現載入模型:
sess=tf.Session() #加載圖和模型參數 new_saver=tf.train.import_meta_graph('./AE_mnist_model/AE_mnist.meta') new_saver.restore(sess,'./AE_mnist_model/AE_mnist')得到我們的計算圖,也就是模型結構:
graph=tf.get_default_graph()我們也可以看看在模型中保存了什么
print(graph.get_all_collection_keys()) #['queue_runners', 'recon', 'summaries', 'train_op', 'trainable_variables', 'variables']可以發現我們的重構函數recon已經保存在里面了,把它取出來,別忘了還有數據接收接口:
recon=graph.get_collection('recon') X=graph.get_tensor_by_name('X:0') print(recon) #[<tf.Tensor 'Sigmoid_3:0' shape=(?, 784) dtype=float32>]接下來讀一張圖片,并處理一下:
images = [] img = cv2.imread('./mnist/test/4/4_20.png') image=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) images.append(image) images = np.array(images, dtype=np.uint8) images = images.astype('float32') images = np.multiply(images, 1.0/255.0) x_batch = images.reshape(1,28*28)萬事俱備,只需把處理后的圖像丟入數據結構,使用函數重構即可
result=sess.run(recon,feed_dict={X:x_batch}) image_reco=np.multiply(result,255) image_reco=image_reco.reshape(28,28)可視化結果:
plt.imshow(image_reco) plt.show()
更新日志2018-8-15
看到變分自編碼相關知識時,看到AE的一個缺點就是只能生成訓練集類似的東東,也就是說如果我拿手寫數字來訓練,模型生成的東東一定就是手寫數字,然后我就去拿著個模型試了一下,隨便丟一張圖片進來:
比如犬夜叉:
然后處理一下:
也就是將彩圖轉為灰度圖并resize成網絡圖片接受接口所需的維度,即28×2828×28大小,變成了這樣
生成一下
果然重構的圖片長得像數字,是個8還是個2。
事實證明:使用AE做圖像重構,生成的結果一定是與訓練集內容相似的東東
后記
下一篇就來看看何為變分自編碼,并實現它
訓練代碼:鏈接:https://pan.baidu.com/s/1HLwWo6T4QBPJxtHE5InQeA 密碼:64rg
測試代碼:鏈接:https://pan.baidu.com/s/1wIjG9KFkDsB1XFB98URcmw 密碼:x7v9
數據集:鏈接:https://pan.baidu.com/s/1UJTAavqEPTCetgMSf-hYTw 密碼:klcl
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的【TensorFlow-windows】学习笔记五——自编码器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《冒险岛手游》背景故事详解 冒险岛手游N
- 下一篇: 《武动乾坤》武祖讲道之黑暗之殿技能搭配小