机器学习之使用Python搭建神经网络

最近为了找新的工作而一筹莫展,不过闲下来的时间学些东西也是不错的,于是准备系统的学一下深度学习和神经网络相关的知识。

首先选择阅读的是《Python神经网络编程》这本书,不得不说,这是本好书,这本书内容和国内所流行“大而全”的书完全不一样,通过一个小实例全篇100来行的 代码完成了一个三层的神经网络搭建,并且花费了大量的篇幅介绍神经网络的基础而没有上来就展示各种数学原理。

本文就是对于这本书的笔记和总结。

  • 线性分类器 --- y= Cx(其中C为常数)

1、 目标值为y,而x则为输入值,通过随机初始化一个C,用于求的y值与目标值(已知)进行求差(目标误差E)。

2、 误差/x并且*参数(可调步进),求得需要对于随机C的更改。

3、 继续以该C进行其他已知集的学习,最终得到一个运行可以将所有点分隔的C常数。

  • 神经网络 --- 多层多节点的形式进行的分类器,以多分类器的方式,尽可能的进行数据的分隔

一般采用S函数的进行作为节点的计算处理 y = 1/(1+e^(-x)) 模拟神经元的阈值

input数据(第一层) | 第二层 | 隐藏层处理结果作为第三层输入 | 第三层 | output数据

在第一层负责输入数据进入第二层,输入数据进行权重乘法(矩阵点乘)

层2节点1的输入:w1,1·input1+w2,1·input2

层2节点2的输入:w1,2·input1+w2,2·input2

其中w代表权重,例如w1,1指初始input值通过第一层的1节点向第二层的节点1传输的权重

到达第2层以后的节点后,得到的加权输入值,应当经过S函数的计算,将该值进行再次的迭代输入下一层

通过多层处理后,最终得到的结果和已知的结果做对比,并且反向传输进行参数调整,所有的误差E也应当以权的形式进行返回调整一开始随机出的 参数w们(有几层就有几个矩阵)。

对于误差进行一个学习因子的相乘,这样可以不会造成过大的步进。

跑完数据集后,最终可以得到一个效果不错的w们,即训练结束。

# --coding:utf-8--
import numpy
import scipy.special as s


class NeuralNetwork:

    def __init__(self, input_nodes, hidden_nodes, output_nodes, leaning_rate):
        self.in_n = input_nodes
        self.hid_n = hidden_nodes
        self.out_n = output_nodes
        self.l_r = leaning_rate

        # 连接权重矩阵,-1~1的随机数(矩阵的大小需要通过隐藏层节点以及输出层,输入层确定)
        self.wih = (numpy.random.rand(self.hid_n, self.in_n) - 0.5)
        self.who = (numpy.random.rand(self.out_n, self.hid_n) - 0.5)
        # 同样可以采用正态分布的方式进行权重的获取
        # self.wih = numpy.random.normal(0.0, pow(self.hid_n, -0.5), (self.hid_n, self.in_n))
        # self.who = numpy.random.normal(0.0, pow(self.out_n, -0.5), (self.out_n, self.hid_n))
        # S函数处理
        self.activation_function = lambda x: s.expit(x)

    # 训练函数
    def train(self, inputs_list, targets_list):
        # 转化为2维数组
        inputs = numpy.array(inputs_list, ndmin=2).T
        targets = numpy.array(targets_list, ndmin=2).T

        hidden_inputs = numpy.dot(self.wih, inputs)
        hidden_outputs = self.activation_function(hidden_inputs)

        # 第二轮点乘
        final_inputs = numpy.dot(self.who, hidden_outputs)
        # S函数二次处理
        final_outputs = self.activation_function(final_inputs)
        # 计算E(误差)
        output_errors = targets - final_outputs
        # 进行矩阵乘法用于决定误差分配
        hidden_errors = numpy.dot(self.who.T, output_errors)
        # 更新节点j于下一层节点k之间的连接权重关系 W(j,k)=α*E(k)*S(O(k))*(1-S(O(k)))·O(j).T
        self.who += self.l_r * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)),
                                         numpy.transpose(hidden_outputs))
        self.wih += self.l_r * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)),
                                         numpy.transpose(inputs))

    # 运行数据
    def query(self, inputs_list):
        # 将输入转化为2维数组
        inputs = numpy.array(inputs_list, ndmin=2).T
        # 首层点乘结果
        hidden_inputs = numpy.dot(self.wih, inputs)
        # S函数处理完成后的计算结果用于输出进行下一轮运算
        # print(hidden_inputs)
        hidden_outputs = self.activation_function(hidden_inputs)
        # 第二轮点乘
        final_inputs = numpy.dot(self.who, hidden_outputs)
        # S函数二次处理
        final_outputs = self.activation_function(final_inputs)
        return final_outputs

链接