神经网络实践项目——数字奇偶识别

项目:奇偶识别

将一个int型整数转化为32位二进制数作为BP人工神经网络的输入(例如,整数2为10前面加30个0,这32个数字分别为32个输入),0或1作为输出层的输出(该数为偶数,则预期输出d为0;该数为奇数,则预期输出d为1),以这样的模型(32个输入,隐含层16个神经元,输出层1个神经元,学习率参数r的值为0.1)训练1000个回合(训练一回合=训练一次训练集,训练一回合后,打乱训练集,再进行下一回合的训练),然后对测试集进行测试并统计奇偶识别率。
训练集:1000个随机整数和1000个预期输出
测试集:10000个随机整数

注:这里的神经网络模型写的是关于二分类的问题,没有写通用的神经网络类

反向传播,随机梯度下降。

神经网络类:

import java.util.Arrays;

public class NeuralNetworks {

    int input_n; // 输入层结点数
    double[][] w1; // w1[0] 为偏置的权重
    int hidden_n; // 隐藏层结点数
    double[] hidden_layer; // 隐藏层
    double[][] w2; // w2[0] 为偏置的权重
    int output_n; // 输出层结点数
    double[] y; // 输出层
    double alpha; // 学习率
    double b; // 偏置

    public NeuralNetworks(int input_n, int hidden_n, int output_n, double alpha, double b) {
        this.input_n = input_n;
        this.hidden_n = hidden_n;
        this.output_n = output_n;
        this.alpha = alpha;
        this.b = b;
        initial();
    }
    // 初始化
    private void initial() {
        this.w1 = new double[input_n + 1][hidden_n];
        this.hidden_layer = new double[this.hidden_n];
        this.w2 = new double[hidden_n + 1][output_n];
        this.y = new double[output_n];
        initial_w(w1);
        initial_w(w2);
    }
    // 初始化权重
    private void initial_w(double[][] w) {
        for (int i = 0; i < w.length; i++) {
            for (int j = 0; j < w[0].length; j++) {
                w[i][j] = Math.random();
            }
        }
    }
    // 训练模型
    public void train(double[] input_x, double[] t_y) {
        calculate_y(input_x); // 计算输出层
        double[] y_error = calculate_y_error(t_y); // 计算输出层误差
        double[] hidden_error = calculate_hidden_error(y_error); // 计算隐藏层误差
        reNewWeight(this.hidden_layer, this.w2, y_error); // 更新隐藏层到输出层权重
        reNewWeight(input_x, this.w1, hidden_error); // 更新输入层到隐藏层权重
    }
    // 预测
    public void predict(double[] x) {
        calculate_y(x);
        System.out.println(Arrays.toString(this.y));
        if (this.y[0] < 0.5) {
            System.out.println("偶数!!!");
        } else {
            System.out.println("奇数!!!");
        }
    }
    // 更新权重
    private void reNewWeight(double[] in, double[][] w, double[] error) {
        // 更新结点权重
        for (int i = 1; i < w.length; i++) {
            for (int j = 0; j < w[0].length; j++) {
                w[i][j] += (this.alpha * error[j] * in[i - 1]);
            }
        }
        // 更新偏置的权重
        for (int j = 0; j < w[0].length; j++) {
            w[0][j] += (this.alpha * error[j] * this.b);
        }
    }
    // 计算隐藏层误差
    private double[] calculate_hidden_error(double[] y_error) {
        double sum;
        double[] hidden_error = new double[this.hidden_n];
        for (int i = 0; i < this.hidden_n; i++) {
            sum = 0;
            for (int j = 0; j < this.output_n; j++) {
                sum += (y_error[j] * this.w2[i + 1][j]);
            }
            hidden_error[i] = sum * this.hidden_layer[i] * (1 - this.hidden_layer[i]);
        }
        return hidden_error;
    }
    // 计算输出层误差
    private double[] calculate_y_error(double[] t_y) {
        double[] y_error = new double[this.output_n];
        for (int i = 0; i < output_n; i++) {
            y_error[i] = (t_y[i] - this.y[i]) * this.y[i] * (1 - this.y[i]);
        }
        return y_error;
    }
    // 计算输出层值
    private void calculate_y(double[] input_x) {
        calculate_layer(input_x, this.w1, this.hidden_layer); // 计算隐藏层值
        calculate_layer(this.hidden_layer, this.w2, this.y); // 计算输出层值
    }
    // 计算该层的输出值
    private void calculate_layer(double[] in, double[][] w, double[] out) {
        double z;
        for (int i = 0; i < w[0].length; i++) {
            z = w[0][i] * this.b;
            for (int j = 1; j < w.length; j++) {
                z += (w[j][i] * in[j - 1]);
            }
            out[i] = 1 / (1 + Math.exp(-z)); // sigmoid函数
        }
    }
}

主类:

import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Random random = new Random();
        NeuralNetworks bp = new NeuralNetworks(32,16,1,0.1,1);
        double[] t_y = new double[1];
        double[] x;
        ArrayList<Integer> train_datas = new ArrayList<>();
        // 随机生成训练集
        for(int i=0;i<1000;i++){
            train_datas.add(random.nextInt());
        }
		// 训练模型
       for(int k=0;k<1000;k++){
           for(int i=0;i<train_datas.size();i++){
               t_y[0] = (train_datas.get(i) & 1); // 预期输出
               x = get_x(train_datas.get(i));
               bp.train(x,t_y);
           }
       }
        System.out.println("训练完成!!!");
        Scanner in = new Scanner(System.in);
        int k;
        System.out.print("输入数字识别奇偶(输入0结束):");
        while((k = in.nextInt()) != 0){
            x = get_x(k);
            bp.predict(x);
            System.out.print("输入数字识别奇偶(输入0结束):");
        }
        in.close();
    }
    // 将10进制转换成2进制
    public static double[] get_x(int num){
        double[] x = new double[32];
        for(int i=31;i>=0;i--){
            x[i] = (num & 1);
            num >>>= 1;
        }
        return x;
    }
}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值