CupCnn 添加rnn的实现

github地址:

CupDnn地址(给个小星星呗^~^)

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实现......

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章