CupCnn 添加rnn的实现
Posted 阳光玻璃杯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CupCnn 添加rnn的实现相关的知识,希望对你有一定的参考价值。
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实现......
以上是关于CupCnn 添加rnn的实现的主要内容,如果未能解决你的问题,请参考以下文章