github地址:
RNN的原理?
。。。。嗯。。。不想多說,很多介紹其原理的文章,所以這裏就不囉嗦了。
爲什麼推薦CupDnn中實現的rnn?
足夠簡單,可能是最簡單的實現吧,很容易學習。
有例子嗎?
有的。給的例子是計算兩個數相加。比如1+1=2 , 0.5+0.5=1。。。。
額????這需要用深度學習?不需要,但是用rnn來實現別有一番刺激。
大家可以看看使用rnn測試輸出信息:
begin load model
load model finished
please input two numbers(-1~1),input q to quit
please input first one:
0.3
please input second one:
0.3
0.3 + 0.3 = 0.6348119
please input two numbers(-1~1),input q to quit
please input first one:
0.34
please input second one:
0.12
0.34 + 0.12 = 0.49013773
please input two numbers(-1~1),input q to quit
please input first one:
0.56
please input second one:
0.91
0.56 + 0.91 = 1.44746
可以看到很明顯的是對的,雖然有一點誤差。
rnn複雜嗎?重要嗎?
不復雜,就是比全連接多了幾個狀態而已。
重要,自然語言相關的ai場景基本靠的就是rnn,用rnn搞個聊天機器人,ai寫詩,翻譯都是用rnn及其變體,把rnn原理徹底搞明白了,這些貌似很炫酷的東西都很簡單。
實現lstm,gru了嗎?
沒有,原理差不多,只是複雜點而已。
CupCnn爲什麼改名CupDnn
添加了rnn後,已經不止於搭建卷積神經網絡了,所以改名爲深度神經網絡。
實現CupDnn有什麼意義?
就是爲了學習。
CupDnn如何搭建rnn
public void buildAddNetwork() {
InputLayer layer1 = new InputLayer(network,2,1,1);
network.addLayer(layer1);
RecurrentLayer rl = new RecurrentLayer(network,RecurrentLayer.RecurrentType.RNN,2,2,100);
network.addLayer(rl);
FullConnectionLayer fc = new FullConnectionLayer(network,100,2);
network.addLayer(fc);
}
public void buildNetwork(){
network = new Network();
network.setThreadNum(4);
network.setBatch(20);
network.setLrDecay(0.7f);
network.setLoss(new MSELoss());//CrossEntropyLoss
optimizer = new SGDOptimizer(0.9f);
network.setOptimizer(optimizer);
buildAddNetwork();
network.prepare();
}
public void train(List<DataAndLabel> trainLists,int epoes) {
network.fit(trainLists, epoes,null);
}
public Blob predict(Blob in) {
return network.predict(in);
}
public void saveModel(String name){
network.saveModel(name);
}
public void loadModel(String name){
network = new Network();
network.setBatch(2);
network.loadModel(name);
network.prepare();
}
爲什麼用fit?沒什麼,就是train換了個名字,爲什麼不繼續用train?參數變了,必須要換名字。prdict也是一樣。
簡單介紹下這個rnn的例子?
public static Vector<DataAndLabel>genDatas(int samples) {
Vector<DataAndLabel> dals = new Vector<DataAndLabel>();
Random random = new Random();
for(int i=0;i<samples;i++) {
float a = random.nextFloat();
if(random.nextBoolean()) {
a = -a;
}
float b = random.nextFloat();
if(random.nextBoolean()) {
b = -b;
}
float[] data = new float[2];
data[0] = a;
data[1] = b;
float[] label = new float[2];
label[0] = a;
label[1] = a+b;
DataAndLabel tmp = new DataAndLabel(2,2);
tmp.setData(data, label);
dals.add(tmp);
}
return dals;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
AddNetwork aw = new AddNetwork();
aw.buildNetwork();
aw.train(genDatas(10000), 20);
aw.saveModel("model/rnn_add.model");
aw.loadModel("model/rnn_add.model");
Scanner sc = new Scanner(System.in);
while(true) {
System.out.println("please input two numbers(-1~1),input q to quit");
System.out.println("please input first one:");
String tmp = sc.next();
if(tmp.equals("q")) {
break;
}
float a = Float.parseFloat(tmp);
System.out.println("please input second one:");
tmp = sc.next();
if(tmp.equals("q")) {
break;
}
float b = Float.parseFloat(tmp);
Blob in = new Blob(1,1,1,2);
float[] inData = in.getData();
inData[0] = a;
inData[1] = b;
Blob result = aw.predict(in);
float[] resultData = result.getData();
System.out.println(a+" + "+b+" = "+resultData[1]);
}
System.out.println("rnn done");
}
首先,genDatas用來生成-1~1之間的隨機數。
每次生成兩個數:(a,b)。好的,(a,b)會被送入rnn,因此rnn的seq也就是序列長度爲2。那邊標籤呢?標籤爲(a,a+b),因爲我們要計算兩個數的和。
然後構建神經網絡。
構建神經網絡的時候請注意,這裏每次送入的是(a,b)兩個數,標籤是(a,a+b),rnn的batch的神經網絡的bath/seq。
有點懵逼嗎?
public void buildAddNetwork() {
InputLayer layer1 = new InputLayer(network,2,1,1);
network.addLayer(layer1);
RecurrentLayer rl = new RecurrentLayer(network,RecurrentLayer.RecurrentType.RNN,2,2,100);
network.addLayer(rl);
FullConnectionLayer fc = new FullConnectionLayer(network,100,2);
network.addLayer(fc);
}
public void buildNetwork(){
network = new Network();
network.setThreadNum(4);
network.setBatch(20);
network.setLrDecay(0.7f);
network.setLoss(new MSELoss());//CrossEntropyLoss
optimizer = new SGDOptimizer(0.9f);
network.setOptimizer(optimizer);
buildAddNetwork();
network.prepare();
}
這裏,network的batch爲20,如果是圖片,就意味着一次輸入20張圖片。但是對於rnn,因爲他的序列長度爲2,也就是它一次處理兩張圖片,所以相當於batch等於10了。所以創建rnn的時候,這裏,不要把網絡的batch設置爲奇數。不要問我爲什麼,就是這麼實現的。
因爲rnn後面接了全連接,必須把兩者兼容起來。rnn是有序列長度的,而全連接是沒有序列長度的。
我有沒有參考別人的代碼
主要參考tiny_dnn和darknet。
darknet是什麼?
darknet太棒了。用darknet實現alpha go的算法,做個圍棋機器人?是的,作者已經做了。yolo?yolo是極好的多目標檢測模型.....還可以訓練寫詩機器人,還有炫酷的nightmare。。。。作者碼代碼的能力太強了,沒有任何依賴,純c+cuda實現......