【caffe-Windows】关于LSTM的简单小例子
前言
這里主要是看到了一個簡單的LSTM例子,比上一個coco簡單很多,所以在這里記錄一下,便于后續的分析,參考博客在上一篇文章的末尾提到過:Recurrent neural nets with Caffe
需要說明的是這個例子也并非原原本本的使用caffe自帶的LSTM,而是加入了一些東西,所以我們還是得新增層
國際慣例,代碼鏈接:
作者提供GitHub:https://github.com/christopher5106/last_caffe_with_stn
博主提供云盤:鏈接:http://pan.baidu.com/s/1i474Dd7 密碼:31x8
第一步
首先對比一下兩個proto,看看我們的caffe-Windows少了哪幾個層。一般而言,操作多了就會發現,我們的第一反應去看看message LayerParameter這里面登記的ID,可以發現作者添加了以下幾層:
①LSTM層:對應lstm_layer.hpp和lstm_layer.cpp注意這個地方由于上一篇博客配置過LSTM,而且此處的LSTM與上一篇博客實現不同,所以最好是重新解壓一個caffe-Windows執行添加層的操作
添加ID為
optional LSTMParameter lstm_param = 201;添加參數為 message LSTMParameter {optional uint32 num_output = 1; // The number of outputs for the layeroptional float clipping_threshold = 2 [default = 0.0];optional FillerParameter weight_filler = 3; // The filler for weightoptional FillerParameter bias_filler = 4; // The filler for the biasoptional uint32 batch_size = 5 [default = 1]; }②Repeat層:對應repeat_layer.hpp和repeat_layer.cpp
添加ID為
optional RepeatParameter repeat_param = 202;添加參數為 message RepeatParameter {optional uint32 num_repeats = 1; // The number of outputs for the layeroptional int32 axis = 2 [default = 1]; }③PowerFile層:對應power_file_layer.hpp和power_file_layer.cpp添加ID為
添加參數為
// added by Kaichun Mo message PowerFileParameter {optional string shift_file = 1; } ④loc_loss層:對應loc_loss_layer.hpp和loc_loss_layer.cpp添加ID為
添加ID為
⑥STLoss層:對應st_loss_layer.hpp和st_loss_layer.cpp
添加ID為
optional STLossParameter st_loss_param = 145;添加內容為 message STLossParameter {// Indicate the resolution of the output images after ST transformationrequired int32 output_H = 1;required int32 output_W = 2; }⑦smooth_L1_loss層:對應smooth_L1_loss_layer.hpp和smooth_L1_loss_layer.cpp無ID無參數
這一步的主要問題在于:
①新拷貝一個caffe-Windows再添加層,因為我第一次是將lstm_layer.hpp和lstm_layer.cpp都換了個名字,但是一直編譯不成功出錯。有C++大牛的話可以嘗試一下,也算是一種挑戰。
②添加層的方法沒有寫詳細,強烈建議大家一層一層添加,否則很容易出錯,而且你不知道錯誤原因何在。而且每一層添加完成測試的方法在上上篇博客有說明,就是單獨對這個cpp編譯會顯示成功。
多句嘴:仔細、仔細、仔細
第二步
很多人在使用matlab接口的時候會說:“哎呀,咋有崩潰了啊”,“哎呀,又閃退了”,“又未響應了”。這種情況我的解決方法是使用exe調試,當然每個人有每個人的調試方法,都靠自己探索的。
所以第二步,先不在MATLAB中進行使用,而是測試一下我們書寫的LSTM的prototxt文件是否正確,新手一般都會出現什么parameterfailed什么的錯誤,反正大概意思就是不存在這個層。那么你就得回到第一步再檢查一遍了,提示的是誰,就檢查誰
廢話說多了,下面開始測試。使用的模型來源于參考博客,先看看網絡結構
看著挺簡單的,先介紹一下輸入(從原始博客翻譯過來):
data:是T*N*I維度,其中I代表序列每一步中數據的維度(例子中為1),T*N代表序列長度,其中N是batchsize批大小。約束是數據大小必須是N的整數倍
clip:是T*N維度,如果clip=0,隱狀態和記憶單元就會被初始化為0,如果不是的話,之前的值將會被使用
label:每一步的預測輸出
根據模型搭建網絡(lstm.prototxt)如下:
name: "LSTM" input: "data" input_shape { dim: 320 dim: 1 } input: "clip" input_shape { dim: 320 dim: 1 } input: "label" input_shape { dim: 320 dim: 1 } layer {name: "Silence"type: "Silence"bottom: "label"include: { phase: TEST } } layer {name: "lstm1"type: "Lstm"bottom: "data"bottom: "clip"top: "lstm1"lstm_param {num_output: 15clipping_threshold: 0.1weight_filler {type: "gaussian"std: 0.1}bias_filler {type: "constant"%偏置初始化為0}} } layer {name: "ip1"type: "InnerProduct"bottom: "lstm1"top: "ip1"inner_product_param {num_output: 1weight_filler {type: "gaussian"std: 0.1}bias_filler {type: "constant"}} } layer {name: "loss"type: "EuclideanLoss"bottom: "ip1"bottom: "label"top: "loss"include: { phase: TRAIN } }有了網絡模型,需要配置一個solver.prototxt去調用它 net: "lstm.prototxt" test_iter: 1 test_interval: 2000000 base_lr: 0.0001 momentum: 0.95 lr_policy: "fixed" display: 200 max_iter: 100000 solver_mode: CPU average_loss: 200 #debug_info: true接下來建立一個test.bat用于測試我們的caffe是否搭建好,是否適用于此prototxt,其中test.bat的內容如下 E:\CaffeDev2\caffe-windows\Build\x64\Release\caffe.exe train -solver=solver.prototxt pause看看我的目錄結構,主要還是為了強調路徑問題
如果這一步出錯,請重新操作第一步
第三步
既然模型沒問題了,那么就可以添加數據進行預測了。采用參考博文中的輸入函數進行測試。
在此之前,參考前面的配置MATLAB接口的博文,確保自帶的classification.m能夠正常運行。
之后我們來測試一下模型預測效果:
①添加環境變量
clear clc addpath('../..') caffe.reset_all caffe.set_mode_cpu②加載模型 solver=caffe.Solver('solver.prototxt');運行看看,崩潰了請重新核對路徑以及MATLAB接口的配置還有第二步是否能成功 >> solversolver = Solver (具有屬性):net: [1x1 caffe.Net]test_nets: [1x1 caffe.Net]設置遺忘門的偏置為5.0③創建數據集
a=0:0.01:32; a=a(1:end-1); d=0.5 * sin(2*a) - 0.05 * cos( 17*a + 0.8 ) + 0.05 * sin( 25 * a + 10 ) - 0.02 * cos( 45 * a + 0.3); d = d / max(max(d), -min(d)); d = d - mean(d);④訓練 niter=5000; solver.net.blobs('clip').set_data(solver.net.blobs('clip').get_data*0+1); train_loss =zeros(1,niter); for i=1:niterif mod(i,1000)==0fprintf('iter=%d\n',i);endseq_idx = mod(i ,(length(d) / 320));mid=solver.net.blobs('clip').get_data();solver.net.blobs('clip').set_data([seq_idx > 0,mid(2:end)]);solver.net.blobs('label').set_data(d( seq_idx * 320+1 : (seq_idx+1) * 320 ));solver.step(1)train_loss(i)= solver.net.blobs('loss').get_data(); end畫出來看看 plot(1:niter,train_loss)再測試一下 preds=zeros(length(d)); solver.test_nets.blobs('clip').set_data(solver.test_nets.blobs('clip').get_data*0+1) for i=1:length(d)mid2=solver.test_nets.blobs('clip').get_data();solver.test_nets.blobs('clip').set_data([i>0,mid2(2:end)]);solver.test_nets.forward_prefilled()mid2=solver.test_nets.blobs('ip1').get_data();preds(i)=mid2(1); end figure plot(preds) hold on plot(d) hold off
第四步
感覺和參考博文中的結果差距很大啊,去Python中測試一下
import caffe solver = caffe.SGDSolver('solver.prototxt') solver.net.params['lstm1'][2].data[15:30]=5 import numpy as np a = np.arange(0,32,0.01) d = 0.5*np.sin(2*a) - 0.05 * np.cos( 17*a + 0.8 ) + 0.05 * np.sin( 25 * a + 10 ) - 0.02 * np.cos( 45 * a + 0.3) d = d / max(np.max(d), -np.min(d)) d = d - np.mean(d) niter=5000 train_loss = np.zeros(niter) solver.net.params['lstm1'][2].data[15:30]=5 solver.net.blobs['clip'].data[...] = 1 for i in range(niter) :seq_idx = i % (len(d) / 320)solver.net.blobs['clip'].data[0] = seq_idx > 0solver.net.blobs['label'].data[:,0] = d[ seq_idx * 320 : (seq_idx+1) * 320 ]solver.step(1)train_loss[i] = solver.net.blobs['loss'].data import matplotlib.pyplot as plt plt.plot(np.arange(niter), train_loss)solver.test_nets[0].blobs['data'].reshape(2,1) solver.test_nets[0].blobs['clip'].reshape(2,1) solver.test_nets[0].reshape() solver.test_nets[0].blobs['clip'].data[...] = 1 preds = np.zeros(len(d)) for i in range(len(d)):solver.test_nets[0].blobs['clip'].data[0] = i > 0preds[i] = solver.test_nets[0].forward()['ip1'][0][0] plt.plot(np.arange(len(d)), preds) plt.plot(np.arange(len(d)), d) plt.show() 然而也無法復現原文效果,有對Python比較了解的大牛希望能夠在評論區給出相關測試意見。
難道是作者博文寫錯了?這個以后再探討。
總結:
通過這兩個關于LSTM的博客發現,不同的人對LSTM的改編都有所不同,根據不同的任務,可以對LSTM做相應的改動,使用方法也不盡相同。
但是語法結構應該是相似的,對比一下兩篇博文中關于LSTM層的寫法可能就會有不同的收獲
總結
以上是生活随笔為你收集整理的【caffe-Windows】关于LSTM的简单小例子的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 再次遇到golang乱码问题,用simp
- 下一篇: 【caffe-Windows】添加工程-