机器学习-学习笔记(Java) 感知器(一)

因为代码需要在C#环境跑起来,所以先用Java来进行编写测试。


感知器

单纯的感知器其实就是一个决策程序(多输入,单输出),即给出多个输入,根据每个输入的权值,进行相乘,最后结果相加,最后给出的阈值相比较,而输出1 or -1(在神经网络称之为激活 或 抑制),所以感知器一般是用来判断是与不是。
举个例子,判断一个数字是偶数嘛(你会说,这个程序这么简单,也叫感知器。。。)?那如果判断这个数能不能被另一个数整除呢?而这个程序也相应的可以解决判断偶数问题,然而却多了一个输入,在感知器中,减少输入还是很关键的。
但是这里就会想到,那之前说的不是根据权值相乘累加判断嘛?判断整除偶数怎么能算感知器呢?这里我是这样认为的,所谓感知器,不仅仅是权值相乘累加,而是一种判断,就像一个人,去判断你面前的这个字是黑色的,答案为是或者不是,而权值计算,我认为是对数字图像的一种抽象表现,即易理解、易抽象,这里的话,我们完全没有必要非要按照这个来,只需要理解感知器为激活或者抑制即可(具体实现可以自己实现,没必要非要死搬硬照)。
这里的权值计算,是为了让训练感知器而准备的,就拿上面的判断偶数来解释,我们知道,我们学习感知器,就是为了机器学习,那偶数判断,有何学习的余地?我只能说,这个感知器已经训练成熟,完全不需要进行训练了- -所以省去了权值计算的步骤。
等会我会写一个权值计算判断偶数的感知器,并进行训练,大家可以看看,完全没有必要,结果因训练集的不同而产生了随机性。
但是世间万物的规律不是那么好追寻的,所以我们只能进行已有数据进行训练。

训练感知器

训练时,分为二种情况,即训练集线性可分、不可分。

训练集线性可分

先讨论线性可分时的情况。

就拿西瓜书第一章的例子,西瓜的好坏。

这里写图片描述

NumMath.java

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package util;


/**
 *
 * @author lol
 */
public class NumMath {

    public static double sum(double[]...values) {
        int length = values.length;
        if (length == 0) {
            return 0;
        } else if (length == 1) {
            double sum = 0;
            for (double v : values[0]) {
                sum += v;
            }
            return sum;
        }
        int len = values[0].length;
        for (int i = 0; i < length; i++) {
            len = Math.min(len, values[i].length);
        }
        double[] array = new double[len];
        for (int j = 0; j < length; j++) {
            for (int i = 0; i < len; i++) {
                if (j != 0) {
                    array[i] *= values[j][i];
                } else {
                    array[i] = values[j][i];
                }
            }
        }
        return sum(array);
    }

    private static void testOfSum() {
        System.out.print("Run testOfSum: ");
        double[] w = {1, 2, 3};
        double[] v = {1, 0, 1};
        System.out.println(sum(w, v));
    }

    public static void main(String[] args) {
        testOfSum();
        // 输出 Run testOfSum: 4.0
    }
}

Perceptron.java

package main;

import java.util.Arrays;
import java.util.Random;
import util.NumMath;

public class Perceptron {

    private double[] weights;
    private double threshold;

    public Perceptron(double[] weights) {
        this.weights = weights;
        this.threshold = 0;
    }

    public Perceptron(double[] weights, double threshold) {
        this.weights = weights;
        this.threshold = threshold;
    }

    public double[] getWeights() {
        return weights;
    }

    public void setWeights(double[] weights) {
        this.weights = weights;
    }

    public double getThreshold() {
        return threshold;
    }

    public void setThreshold(double threshold) {
        this.threshold = threshold;
    }

    public int getOutput(double... values) {
        if (this.getValue(values) >= this.threshold) {
            return 1;
        }
        return -1;
    }

    public double getValue(double... values) {
        return NumMath.sum(this.weights, values);
    }

    public double[] train(double[][] test, double[] trueOutput, double studySpeed) {
        double[] o = new double[test.length];
        boolean flag = true;
        while (flag) {
            flag = false;
            // System.out.println("新的一轮!");
            for (int i = 0; i < test.length; i++) {
                o[i] = new Perceptron(this.weights, this.threshold).getOutput(test[i]);
                if (o[i] != trueOutput[i]) {
                    this.threshold -= studySpeed * (trueOutput[i] - o[i]);
                    // System.out.print(threshold + "= ");
                    for (int j = 0; j < weights.length; j++) {
                        weights[j] += studySpeed * (trueOutput[i] - o[i]) * test[i][j];
                        // System.out.print(weights[j] + ", ");
                    }
                    // System.out.println(" = " + new Perceptron(this.weights, this.threshold).getValue(test[i]));
                    i--;
                    flag = true;
                } else {
                    // System.out.println("第" + i + "个对了!");
                }
            }
        }

        return weights;
    }

    @Override
    public String toString() {
        return "Perceptron{" + "weights=" + Arrays.toString(weights) + ", threshold=" + threshold + '}';
    }

    public static void main(String[] args) {
        Random r = new Random();
        double[] w = {0, 0, 0};
        double t = 0;
        Perceptron p = new Perceptron(w, t);
        double[][] d = {
            {1, 1, 0},
            {0, 1, 0},
            {0, 1, 1},
            {1, 0, 2},
            {0, 2, 1},
            {1, 1, 2},
            {2, 1, 2},
            {2, 2, 2},
        };
        double[] tf = {1, 1, -1, -1, -1, 1, 1, 1};
        p.train(d, tf, 0.001);
        System.out.println(p);
        System.out.println(p.getOutput(0, 1, 2));
        // 输出 Perceptron{weights=[0.020000000000000004, 0.008, -0.01], threshold=0.008}
        // -1
    }
}

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值