神經網絡JOONE的實踐


什么是joone

  • Joone是一個免費的神經網絡框架來創建,訓練和測試人造神經網絡。目標是為最熱門的Java技術創造一個強大的環境,為熱情和專業的用戶。

  • Joone由一個中央引擎組成,這是Joone開發的所有應用程序的支點。Joone的神經網絡可以建立在本地機器上,在分布式環境中進行培訓,並在任何設備上運行。

  • 每個人都可以編寫新的模塊來實現從核心引擎分發的簡單組件開始的新算法或新架構。主要思想是為圍繞核心框架推出數百萬個人工智能應用的基礎。

一些功能...

  • [x] 監督學習:
  • [x] 前饋神經網絡(FFNN)
  • [x] 遞歸神經網絡(Elman,Jordan,...)
  • [x] 時間延遲神經網絡(TDNN)
  • [x] 標准背支(梯度下降,在線和批量)
  • [x] 彈性支撐(RPROP)

無監督學習:

基礎例子異或運算

  • 可能大家會有疑問為什么還是異或運算,為什么不能換點其他的呢,進行異或運算數據量小,可以取得很好的學習效果.

  • 幾個關鍵點:
  1. LinearLayer 單組神經網絡 線性
  2. SigmoidLayer 單組神經網絡 線性
  3. FullSynapse 連接神經網絡的突觸
  4. NeuralNet 神經網絡容器
  5. Monitor 監視器 類似管理器

  • 基本運用流程
  1. 構造適用於模型的神經網絡
  2. 根據模型控制的數據的流動控制i/o
  3. moniter開啟學習過程
  4. 不得不注意: 單個類必須實現 NeuralNetListener

  • 展現編碼:
	private NeuralNet neuralNet;
	private Monitor monitor;
	private SigmoidLayer out, hidden;
	private LinearLayer in;

	public static void main(String[] args) {
		Xor xor = new Xor();
		xor.init_nulnetwork();
		xor.dualData("res/xor.txt", "res/result.txt");
		// xor.name("res/xor.txt", "res/result.txt");
	    try { Thread.sleep(1000); } catch (InterruptedException doNothing) { }
		xor.interrogate();
	}

	private void interrogate() {

		double[][] inputArray = new double[][] { { 0.0, 1.0 } };
		// set the inputs
		neuralNet.getMonitor().setLearning(false);

		MemoryInputSynapse inputSynapse = new MemoryInputSynapse();
		inputSynapse.setInputArray(inputArray);
		inputSynapse.setAdvancedColumnSelector("1,2");

		neuralNet.removeAllInputs();
		neuralNet.removeAllOutputs();
		neuralNet.addInputSynapse(inputSynapse);
		MemoryOutputSynapse memOut = new MemoryOutputSynapse();
		neuralNet.addOutputSynapse(memOut);
		if (neuralNet != null) {
			neuralNet.getMonitor().setSingleThreadMode(false);
			neuralNet.go();
			for (int i = 0; i < 4; i++) {
				double[] nextPattern = memOut.getNextPattern();
				System.out.println(nextPattern[0]);
			}
			System.exit(0);
		}
	}

	public void dualData(String inpath, String outpath) {

		// 輸入數據突觸
		FileInputSynapse inputSynapse = new FileInputSynapse();
		inputSynapse.setInputFile(new File(inpath));
		inputSynapse.setAdvancedColumnSelector("1,2");
		// 傳入數據突觸
		in.addInputSynapse(inputSynapse);

		// 訓練突觸
		TeachingSynapse Teaching = new TeachingSynapse();
		// 結果對應
		FileInputSynapse in_resultsynapse = new FileInputSynapse();
		in_resultsynapse.setInputFile(new File(inpath));
		in_resultsynapse.setAdvancedColumnSelector("3");

		// 期望結果
		Teaching.setDesired(in_resultsynapse);

		// 輸出數據突觸
		out.addOutputSynapse(Teaching);
		/* Creates the error output file */
		FileOutputSynapse error = new FileOutputSynapse();
		error.setFileName(outpath);
		// error.setBuffered(false);
		Teaching.addResultSynapse(error);
		neuralNet.setTeacher(Teaching);

		monitor.setLearning(true);
		monitor.setTrainingPatterns(4);
		monitor.setTotCicles(2000);
		neuralNet.go();
	}

	public void init_nulnetwork() {
		// 構造三個神經網絡
		in = new LinearLayer("in");
		out = new SigmoidLayer("out");
		hidden = new SigmoidLayer("hidden");

		// 定義每個網絡的神經數
		in.setRows(2);
		hidden.setRows(3);
		out.setRows(1);

		// 創建神經突觸
		FullSynapse synapseone = new FullSynapse();
		FullSynapse synapsetwo = new FullSynapse();

		// 連接突觸 in->hidden
		in.addOutputSynapse(synapseone);
		hidden.addInputSynapse(synapseone);
		// hidden>out
		out.addInputSynapse(synapsetwo);
		hidden.addOutputSynapse(synapsetwo);

		// 創建容器
		neuralNet = new NeuralNet();
		neuralNet.addLayer(in, NeuralNet.INPUT_LAYER);
		neuralNet.addLayer(out, NeuralNet.OUTPUT_LAYER);
		neuralNet.addLayer(hidden, NeuralNet.HIDDEN_LAYER);
		neuralNet.addNeuralNetListener(this);

		monitor = neuralNet.getMonitor();
		monitor.addNeuralNetListener(this);
		// 學習速度
		monitor.setLearningRate(0.8);
		// 學習梯度
		monitor.setMomentum(0.9);
	}

	@Override
	public void cicleTerminated(NeuralNetEvent arg0) {

	}

	@Override
	public void errorChanged(NeuralNetEvent arg0) {
		Monitor source = (Monitor) arg0.getSource();
		if (source.getCurrentCicle() % 100 == 0)
			System.out.println(source.getCurrentCicle() + " epochs remaining - RMSE = " + source.getGlobalError());
	}

	@Override
	public void netStarted(NeuralNetEvent arg0) {
		System.out.println("star ..............");
	}

	@Override
	public void netStopped(NeuralNetEvent arg0) {
	}

	@Override
	public void netStoppedError(NeuralNetEvent arg0, String arg1) {

	}

運行效果展示

  • 控制台打印內容
star ..............
1900 epochs remaining - RMSE = 0.47600682941789274
1800 epochs remaining - RMSE = 0.4193120542959407
1700 epochs remaining - RMSE = 0.3615907922936926
1600 epochs remaining - RMSE = 0.043037310196610556
1500 epochs remaining - RMSE = 0.029465401358726946
1400 epochs remaining - RMSE = 0.023733896256020553
1300 epochs remaining - RMSE = 0.020388084386553255
1200 epochs remaining - RMSE = 0.01813347388867849
1100 epochs remaining - RMSE = 0.0164837281607376
1000 epochs remaining - RMSE = 0.015209973541172709
900 epochs remaining - RMSE = 0.014188572240857322
800 epochs remaining - RMSE = 0.013346142747488585
700 epochs remaining - RMSE = 0.012636035607807258
600 epochs remaining - RMSE = 0.012026998316013436
500 epochs remaining - RMSE = 0.011497207806982808
400 epochs remaining - RMSE = 0.011030904955155142
300 epochs remaining - RMSE = 0.010616388884900461
200 epochs remaining - RMSE = 0.010244766308025021
100 epochs remaining - RMSE = 0.009909141567578732
  • 可以看出,上面列表中的第一行中的數字合理地接近於零。這是很好的,因為輸入訓練文件的第一行,如列表1所示,被預期結果是為零的。同樣,第二行合理地接近於1,這也很好,因為訓練文件的第二行被預期結果也是為1的。
  • 訓練文件格式
0;0;0
1;0;1
1;1;0
0;1;1

設置的 setAdvancedColumnSelector 可以挑出來的需要的數據內容

存儲問題

如果你在大量數據的訓練,在每一次訓練結束時,當前的結果不會在下一次啟動學習時進行結果保存的.那么解決的辦法是什么呢?

那肯定的java的序列化解決 你只需要的實現Serializable接口.

  • 對於joonetools工具類 只需要 使用load 方法載入即可.

  • 下面給出一個工具類例子:

package extend.java.Seriobject;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * 
 * @author DGW-PC
 * 對象的序列化與反序列化
 */
public class TestSerializable {
	
	private final static String filepath="rouseces/temp.xor";
	public static void main(String[] args) {
		/*User user = new User(123, "dgw", "男");
		TestSerializable serializable = new TestSerializable();
		try {
			serializable.writeObject(user);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
		TestSerializable serializable = new TestSerializable();
		try {
			User object = (User)serializable.readObject();
			System.out.println(object.toString());
		} catch (ClassNotFoundException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	public void writeObject(Object o) throws IOException {
		File file = new File(filepath);
		if (file.exists()) {
			file.delete();
		}
		FileOutputStream outputStream = new FileOutputStream(file);
		ObjectOutputStream objectWrite = new ObjectOutputStream(outputStream);
		
		objectWrite.writeObject(o);
		objectWrite.close();
		outputStream.close();
	}
	
	@SuppressWarnings("resource")
	public Object  readObject() throws IOException, ClassNotFoundException {
		File file = new File(filepath);
		if (!file.exists()) {
			throw new FileNotFoundException();
		}
		FileInputStream inputStream = new FileInputStream(file);
		ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
		return objectInputStream.readObject();
	}
}

其他問題

實現NeuralNetListener 神經網絡訓練過程中的一些監聽函數:

  1. icleTerminated:每個循環結束后輸出的信息
  2. errorChanged:神經網絡錯誤率變化時候輸出的信息
  3. netStarted:神經網絡開始運行的時候輸出的信息
  4. netStopped:神經網絡停止的時候輸出的信息

驗證代碼:

private void interrogate() {

		double[][] inputArray = new double[][] { { 0.0, 1.0 } };
		// 設置輸入
		neuralNet.getMonitor().setLearning(false);

		MemoryInputSynapse inputSynapse = new MemoryInputSynapse();
		inputSynapse.setInputArray(inputArray);
		inputSynapse.setAdvancedColumnSelector("1,2");

		neuralNet.removeAllInputs();
		neuralNet.removeAllOutputs();
		neuralNet.addInputSynapse(inputSynapse);
		MemoryOutputSynapse memOut = new MemoryOutputSynapse();
		neuralNet.addOutputSynapse(memOut);
		if (neuralNet != null) {
			neuralNet.getMonitor().setSingleThreadMode(false);
			neuralNet.go();
			for (int i = 0; i < 4; i++) {
				double[] nextPattern = memOut.getNextPattern();
				System.out.println(nextPattern[0]);
			}
			System.exit(0);
		}
	}

  • 當輸入0,1輸出內容
100 epochs remaining - RMSE = 0.009909141567578732
[main] [WARN] - org.joone.net.NeuralNet - Termination requested but net appears not to be running.
star ..............
0.9908896675722858
  • 當輸入0,0 是輸出的內容
400 epochs remaining - RMSE = 0.010399344820751158
300 epochs remaining - RMSE = 0.010045322272865264
200 epochs remaining - RMSE = 0.009724485002708847
100 epochs remaining - RMSE = 0.009431977897288895
[main] [WARN] - org.joone.net.NeuralNet - Termination requested but net appears not to be running.
star ..............
0.008214361744075686

由上面的兩個數據內容比較可以知道 在進行4個數據比較過后 ,達到了學習的預期的目的,0.0表示不成立結果為0 ,0.99 表示結果成立,結果為1


封裝joonetools工具類的例子

  • 更多的驗證器例子:請參照官方api文檔
package org.basics.code;

import org.joone.helpers.factory.JooneTools;
import org.joone.net.NeuralNet;

public class Tools {
	  // XOR 輸入值
    private static double[][]	inputArray = new double[][] {
        {0.0, 0.0},
        {0.0, 1.0},
        {1.0, 0.0},
        {1.0, 1.0}
    };
    
    // XOR 期望值
    private static double[][]	desiredArray = new double[][] {
        {0.0},
        {1.0},
        {1.0},
        {0.0}
    };
    
    public static void main(String[] args) {
    	try {
    		// 創建3個sigmoid神經網絡,序列為2 2 1 
            NeuralNet nnet = JooneTools.create_standard(new int[]{ 2, 2, 1 }, JooneTools.LOGISTIC);
                nnet.getMonitor().setSingleThreadMode(true);
                /**
                 * 參數意義:
                 * 1. 網絡容器
                 * 2. 輸入,期末數組
                 * 3.5000 個遞歸梯度
                 * 4. 步進為0.01
                 * 5. 形式為輸出
                 * 6.異步模式
                 */
                double rmse = JooneTools.train(nnet, inputArray, desiredArray,
                        5000, 0.01,
                        200, System.out, false);
                
                // 避免的時間片重疊
                try { Thread.sleep(50); } catch (InterruptedException doNothing) { }
                
                // 更直觀的驗證列表
                System.out.println("Last RMSE = "+rmse);
                System.out.println("\nResults:");
                System.out.println("|Inp 1\t|Inp 2\t|Output");
                for (int i=0; i < 4; ++i) {
                    double[] output = JooneTools.interrogate(nnet, inputArray[i]);
                    System.out.print("| "+inputArray[i][0]+"\t| "+inputArray[i][1]+"\t| ");
                    System.out.println(output[0]);
                }
                
                // 測試結果
                double testRMSE = JooneTools.test(nnet, inputArray, desiredArray);
                System.out.println("\nTest error = "+testRMSE);
            } catch (Exception exc) { exc.printStackTrace(); }
	}

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM