用python编写神经网络_绝不是心血来潮:尝试用python自己写一个神经网络

首先,神经网络是什么?人脑由几千亿由突触相互连接的细胞(神经元)组成。突触传入足够的兴奋就会引起神经元的兴奋。这个过程被称为“思考”。

1540298038712906cbdb7bawAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

我们可以在计算机上写一个神经网络来模拟这个过程。不需要在生物分子水平模拟人脑,只需模拟更高层级的规则。我们使用矩阵(二维数据表格)这一数学工具,并且为了简单明了,只模拟一个有3个输入和一个输出的神经元。

我们将训练神经元解决下面的问题。前四个例子被称作训练集。你可能发现了,输出总是等于输入中最左列的值。所以‘?’应该是1。

15402980623259d54247724wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

训练过程

但是如何使我们的神经元回答正确呢?赋予每个输入一个权重,可以是一个正的或负的数字。拥有较大正(或负)权重的输入将决定神经元的输出。首先设置每个权重的初始值为一个随机数字,然后开始训练过程:

取一个训练样本的输入,使用权重调整它们,通过一个特殊的公式计算神经元的输出。

计算误差,即神经元的输出与训练样本中的期待输出之间的差值。

根据误差略微地调整权重。

重复这个过程10万次。

154029803874341e5760cacwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

最终权重将会变为符合训练集的一个最优解。如果使用神经元考虑这种规律的一个新情形,它将会给出一个很棒的预测。

这个过程就是BP。

计算神经元输出的公式

你可能会想,计算神经元输出的公式是什么?首先,计算神经元输入的加权和,即

1540298038695ec91add7bdwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

接着使之规范化,结果在0,1之间。为此使用一个数学函数--Sigmoid函数:

1540298038666ab3e2b041awAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

Sigmoid函数的图形是一条“S”状的曲线。

15402980388690e142c9d91wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

把第一个方程代入第二个,计算神经元输出的最终公式为:

1540298038813cf95b5e208wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

调整权重的公式

我们在训练时不断调整权重。但是怎么调整呢?可以使用“Error Weighted Derivative”公式:

1540298038923fc52372250wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

为什么使用这个公式?首先,我们想使调整和误差的大小成比例。其次,乘以输入(0或1),如果输入是0,权重就不会调整。最后,乘以Sigmoid曲线的斜率(图4)。

Sigmoid曲线的斜率可以通过求导得到:

15402980389014bc72a3414wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

把第二个等式代入第一个等式里,得到调整权重的最终公式:

154029803926824fa7faf67wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

构造Python代码

虽然我们没有使用神经网络库,但是将导入Python数学库numpy里的4个方法。分别是:

exp--自然指数

array--创建矩阵

dot--进行矩阵乘法

random--产生随机数

“.T”方法用于矩阵转置(行变列)。所以,计算机这样存储数字:

15402980390810a6c18abc7wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

我对每一行源代码都添加了注释来解释所有内容。注意在每次迭代时,我们同时处理所有训练集数据。所以变量都是矩阵(二维数据表格)。下面是一个用Python写地完整的示例代码。

#numpy导入自然指数,创建矩阵,产生随机数,矩阵乘法的方法

from numpy import exp,array,random,dot

class NeuralNetwork(object):

def __init__(self):

#指定随机数发生器种子,保证每次获得相同结果的随机数

random.seed(1)

#对含有3个输入一个输出的单个神经元建模

#即3*1矩阵(树突)赋予随机权重值。范围(-1,1)

#即(a,b)范围的c*d矩阵随机数为(b-a)*random.random((c,d))+a

self.dendritic_weights = 2*random.random((3,1))-1

#Sigmoid函数,s形曲线,用于对输入的加权总和x做(0,1)正规化

#它可以将一个实数映射到(0,1)的区间

def __sigmoid(self,x):

return 1/(1+exp(-x))

#Sigmoid函数的导数(梯度)(当前权重的置信程度,越小代表越可信)

#这里的x指的是1/(1+exp(-x)),即output输出

def __sigmoid_derivative(self,x):

return x*(1-x)

#训练该神经网络,并调整树突的权重

def train(self,training_inputs,training_outputs,number_of_training_iterations):

'''

training_inputs:训练集样本的输入

training_outputs:训练集样本的输出

number_of_training_iterations:训练次数

1.我们使用Sigmoid曲线计算(输入的加权和映射到0至1之间)作为神经元的输出

2.如果输出是一个大的正(或负)数,这意味着神经元采用这种(或另一种)方式,

3.从Sigmoid曲线可以看出,在较大数值处,Sigmoid曲线斜率(导数)小,即认为当前权重是正确的,就不会对它进行很大调整。

4.所以,乘以Sigmoid曲线斜率便可以进行调整

'''

for iteration in range(number_of_training_iterations):

#训练集导入神经网络

output = self.think(training_inputs)

#计算误差(实际值与期望值的差)

error = training_outputs - output

#将误差乘以输入,再乘以S形曲线的梯度

adjustment = dot(training_inputs.T,error*self.__sigmoid_derivative(output))

#对树突权重进行调整

self.dendritic_weights += adjustment

#神经网络

def think(self,inputs):

#输入与权重相乘并正规化

return self.__sigmoid(dot(inputs,self.dendritic_weights))

if __name__ == '__main__':

#初始化神经网络nn

nn = NeuralNetwork()

#初始权重

print("初始树突权重:{}".format(nn.dendritic_weights))

#训练集,四个样本,每个样本有3个输入,1个输出

#训练样本的输入

training_inputs_sample = array([[0,0,1],

[1,1,1],

[1,0,1],

[0,1,1]])

#训练样本的输出

training_outputs_sample = array([[0,1,1,0]]).T

#用训练集训练nn,重复一万次,每次做微小的调整

nn.train(training_inputs_sample,training_outputs_sample,100000)

#训练后的树突权重

print("训练后树突权重:{}".format(nn.dendritic_weights))

#用新数据进行测试

test_result = nn.think(array([1,0,0]))

print('测试结果:{}'.format(test_result))

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

结语

运行后你应该看到这样的结果:

20190717130747780.pngwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

我们做到了!我们用Python构建了一个简单的神经网络!

首先神经网络对自己赋予随机权重,然后使用训练集训练自己。接着,它考虑一种新的情形[1, 0, 0]并且预测了0.99993704。正确答案是1。非常接近!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值