Python神经网络编程笔记
神经元
想一想便知道,当一个人捏你一下以至于你会痛得叫起来的力度便是神经元的阈值,而我们构建的时候也是把这种现象抽象成一个函数,叫作激活函数。
而这里便是我们使用sigmoid函数的原因,它是一个很简单的函数,平滑更接近显示。
$$y=\frac{1}{1+e^{-x}}$$

神经网络传递信号
神经网络便是通过一个一个神经元连接,使用权值x输入的和在通过sigmoid函数得到最终的输出值,然后一层一层的传递下去。
\]
其中,\(O\)为输出矩阵,\(W\)为权值矩阵,\(I\)为输入矩阵。
举个栗子:
假设我们设置一个三层神经网络,分别为输入层,隐藏层(注意:不管我们中间有多少层,中间的都叫隐藏层,我们这里隐藏层只有一层),输出层。
1.输入层->隐藏层:我们输入矩阵是一个(3x1)的矩阵,那么我们设置四个权值,那么我们的第一个权值矩阵(就是输入层->隐藏层的)的维度也就为(4x3),这时我们相乘也就得到输出矩阵(4x1),进行下一步时,这个(4x1)的输出矩阵就变成了输入;
2.隐藏层->输出层:这是我们的输入矩阵是一个(4x1)的矩阵,然后我们要求输出层输出为两个值,那么我们第二个权值矩阵(就是隐藏层->输出层的)的维度也就为(2x4),这时我们相乘也就得到输出矩阵(2x1),也就为最终的结果了。
反向传播
现在我们已经可以收到由前面的层传输过来的结果了,但答案肯定是不准的,那么我们该如何进行改进呢?
毫无疑问,首先我们要计算误差,假设真实值为t,输出值为o,那么误差e就为:
\]

我们按照上图来进行举例说明。
1.更新误差
那么,隐藏层的误差如何确定呢?
我们使用链接\(w_{1,1}\)和链接\(w_{2,1}\)上的分割误差之和来进行更新,也就是
\]
我们也进行带值进行计算
\]
2.使用矩阵进行更新
我们发现上面的公式应用到矩阵运算会很复杂,我们究其本质,最重要的事情是输出误差与链接权重\(w_{ij}\)的乘法。较大的权重就意味着携带较多的输出误差给隐藏层,这些分数的分母是一种归一化因子。如果我们忽略这种因子,那么我们仅仅失去后溃误差的大小。
也就是这里我们使用\(e_1*w_{1,1}\)来代替\(e_1*w_{1,1}/(w_{1,1}+w_{2,1})\) 。那么我们就可以很容易的进行矩阵运算进行误差更新了。
\]
3.更新权重
在神经网络中,我们采用梯度下降法来寻找最优的权重值。神经网络本身的输出函数部署一个误差函数,但我们知道,由于误差是目标训练值与实际输出值之间的差值,因此我们可以很容易的构建误差函数,即
\]
为什么我们要构建平方项呢?为何不用绝对值误差呢?原因有三
- 使用误差的平方,我们可以很容易的使用代数计算出梯度下降的斜率;
- 误差函数平滑连续,这是的梯度下降法很好地发挥作用,没有间断,也没有突然的跳跃;
- 越接近最小值,梯度越小,这意味着,如果我们使用这个函数调节步长,超调的风险就会变得很小。
现在我们要更新\(w_{j,k}\)的权值,那么来推导一下它的更新公式:
首先有
\]
然后根据链式法则得到:
\]
然后我们对其求偏导:
= -2(t_k-o_k) \cdot \frac{\partial}{\partial W_{j,k}}sigmoid(\sum_{j}w_{j,k}\cdot o_j)\\
= -2(t_k-o_k) \cdot sigmoid(\sum_{j}w_{j,k}\cdot o_j)(1-sigmoid(\sum_{j}w_{j,k}\cdot o_j)) \cdot \frac{\partial}{\partial W_{j,k}}(\sum_{j}w_{j,k}\cdot o_j)\\
= -2(t_k-o_k) \cdot sigmoid(\sum_{j}w_{j,k}\cdot o_j)(1-sigmoid(\sum_{j}w_{j,k}\cdot o_j)) \cdot o_j\]
这样我们就得到了最后的权重更新公式:
\]
其中:
\]
输入与输出
1.输入
我们观察sigmoid函数注意到,当输入值变大,激活函数也就会越来越平坦,权重的改变取决于激活函数的梯度,小梯度也就意味着限制了神经网络的学习能力,这就是所谓的饱和神经网络。因此,我们要尽量保持小的输入。
但有趣的是,当输入信号太小,计算机便会损失精度,所以我们要保持输入范围在0.0~1.0之间,但输入为0的话会将\(o_j\)设置为0,这样的权重更新表达式就会等于0,从而造成学习能力的丧失,我们需要加上一个小小的偏移,例如0.01,避免输入0带来的麻烦。
2.输出
我们使用激活函数得到的值的范围会被限制在0~1之间,注意:逻辑函数甚至不能取到1.0,只能接近于1.0.数学家们称之为渐进于1.0.
因此,我们需要调整目标值,匹配激活函数的可能输出,常见的使用范围为0.01.0之间,但我们是取不到0.0和1.0的,所以这里我们也要进行偏移,例如0.010.99.
随机初始权重
和输入输出一样,初始的权重设置也要遵从同样地原则。过大的初始权重会造成大的信号传递给激活函数,导致网络饱和,从而降低学习到更好的权重的能力,因此应该避免大的初始权重值。
我们可以从-1.0~+1.0之间随机均匀地挑选初始权重。而我们也希望初始权重的分布是均匀的,经过数学家们的证明,我们有一个比较好的挑选方式,那就是从均值为0、标准方差等于节点传入链接数量平方根倒数的正态分布中进行采样。
总而言之,我们要禁止将初始权重设定为0或者将初始权重设定为像痛得恒定值,这样会很糟糕。
代码实现
import numpy as np
import scipy.special
import matplotlib.pyplot as plt
# neural network class definition
class NeuralNetwork:
def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
# set number of nodes in each input, hidden, output layer
self.inodes = inputnodes
self.hnodes = hiddennodes
self.onodes = outputnodes
# learning rate
self.lr = learningrate
# 初始权重矩阵
self.wih = np.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))
self.who = np.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))
# 激活函数
self.activation_function = lambda x: scipy.special.expit(x)
pass
def train(self, inputs_list, targets_list):
# 输入
inputs = np.array(inputs_list, ndmin=2).T
targets = np.array(targets_list, ndmin=2).T
# 隐藏层计算
hidden_inputs = np.dot(self.wih, inputs)
hidden_outputs = self.activation_function(hidden_inputs)
# 输出层计算
final_inputs = np.dot(self.who, hidden_outputs)
final_outputs = self.activation_function(final_inputs)
# 误差计算
output_errors = targets - final_outputs
hidden_errors = np.dot(self.who.T, output_errors)
# 反向传播更新权值
self.who += self.lr * np.dot((output_errors * final_outputs * (1.0 - final_outputs)), np.transpose(hidden_outputs))
self.wih += self.lr * np.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), np.transpose(inputs))
pass
def query(self, inputs_list):
# 输入
inputs = np.array(inputs_list, ndmin=2).T
# 隐藏层计算
hidden_inputs = np.dot(self.wih, inputs)
hidden_outputs = self.activation_function(hidden_inputs)
# 输出层计算
final_inputs = np.dot(self.who, hidden_outputs)
final_outputs = self.activation_function(final_inputs)
return final_outputs
if __name__ == '__main__':
input_nodes = 784
hidden_nodes = 200
output_nodes = 10
learning_rate = 0.2
nn = NeuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
# 加载数据
train_data_file = open("./mnist_train.csv", "r")
train_data_list = train_data_file.readlines()
train_data_file.close()
print("数据读取完毕")
# 可视化
# all_values = train_data_list[0].split(',')
# image_array = np.asfarray(all_values[1:]).reshape((28, 28))
# plt.imshow(image_array, cmap="Greys", interpolation='None')
# plt.show()
epochs = 2
for e in range(epochs):
print("\t===== epochs %d =====\t" % (e+1))
for record in train_data_list:
all_values = record.split(',')
inputs = (np.asfarray(all_values[1:]) / 255 * 0.99) + 0.01
targets = np.zeros(output_nodes) + 0.01
targets[int(all_values[0])] = 0.99
nn.train(inputs, targets)
# 预测
test_data_file = open("./mnist_test.csv", "r")
test_data_list = test_data_file.readlines()
test_data_file.close()
print(len(test_data_list))
t_num = 0
for line in test_data_list:
all_values = line.split(',')
y = all_values[0]
y_pred = np.argmax(nn.query(np.asfarray(all_values[1:]) / 255 * 0.99 + 0.01))
if int(y) == int(y_pred):
t_num += 1
print(t_num)
print(t_num * 1.0 / len(test_data_list))
这份三层神经网络对mnist手写数据集能达到97%的准确度。
Python神经网络编程笔记的更多相关文章
- python核心编程--笔记
python核心编程--笔记 的解释器options: 1.1 –d 提供调试输出 1.2 –O 生成优化的字节码(生成.pyo文件) 1.3 –S 不导入site模块以在启动时查找pyt ...
- 学习推荐《Python神经网络编程》中文版PDF+英文版PDF+源代码
推荐非常适合入门神经网络编程的一本书<Python神经网络编程>,主要是三部分: 介绍神经网络的基本原理和知识:用Python写一个神经网络训练识别手写数字:对识别手写数字的程序的一些优化 ...
- 《Python神经网络编程》中文版PDF+英文版PDF+源代码,业界良心书
下载:https://pan.baidu.com/s/1hI6wMPq4UFvEmpgF3ZV1jg 关于内容 这本书主要揭示神经网络背后的概念,并介绍如何通过Python实现神经网络.全书主要讲了三 ...
- Python 异步编程笔记:asyncio
个人笔记,不保证正确. 虽然说看到很多人不看好 asyncio,但是这个东西还是必须学的.. 基于协程的异步,在很多语言中都有,学会了 Python 的,就一通百通. 一.生成器 generator ...
- python socket编程笔记
用python实现一个简单的socket网络聊天通讯 (Linux --py2.7平台与windows--py3.6平台) 人生苦短之我用Python篇(socket编程) python之路 sock ...
- python核心编程--笔记(不定时跟新)(转)
的解释器options: 1.1 –d 提供调试输出 1.2 –O 生成优化的字节码(生成.pyo文件) 1.3 –S 不导入site模块以在启动时查找python路径 1.4 –v ...
- python核心编程笔记(转)
解释器options: 1.1 –d 提供调试输出 1.2 –O 生成优化的字节码(生成.pyo文件) 1.3 –S 不导入site模块以在启动时查找python路径 1.4 –v 冗 ...
- 《Python神经网络编程》的读书笔记
文章提纲 全书总评 读书笔记 C01.神经网络如何工作? C02.使用Python进行DIY C03.开拓思维 附录A.微积分简介 附录B.树莓派 全书总评 书本印刷质量:4星.纸张是米黄色,可以保护 ...
- Python核心编程笔记(类)
Python并不强求你以面向对象的方式编程(与Java不同) # coding=utf8 class FooClass(object): version = 0.1 def __init__(self ...
随机推荐
- mqtt协议系统设计参考
作者:极寒链接:https://zhuanlan.zhihu.com/p/28525517来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 回顾自己的工作经历最遗憾的是没 ...
- 微信中的APP、公众号、小程序的openid及unionid介绍
微信中的APP.公众号.小程序的openid及unionid介绍 1.unionid 如果开发者拥有多个移动应用.网站应用.和公众帐号(包括小程序),可通过 UnionID 来区分用户的唯一性,因为只 ...
- 70-persistent-net.rules无法自动生成,解决方法
无法自动生成70-persistent-net.rules文件的原因: 在更换linux内核前修改ifcfg-eth0文件,更换内核,使用dhclient无法动态分配IP,删掉70-persisten ...
- python3下scrapy爬虫(第十四卷:scrapy+scrapy_redis+scrapyd打造分布式爬虫之执行)
现在我们现在一个分机上引入一个SCRAPY的爬虫项目,要求数据存储在MONGODB中 现在我们需要在SETTING.PY设置我们的爬虫文件 再添加PIPELINE 注释掉的原因是爬虫执行完后,和本地存 ...
- 1、简述在java网络编程中,服务端程序与客户端程序的具体开发步骤?
网络编程分为UDP通信和TCP通信 UDP协议: 发送端:1.创建DatagramSocket对象.2.创建DatagramPacket对象,并封装数据.3.发送数据.4.释放 资源. 接收端:1.创 ...
- Java操作redis客户端Jedis使用
1.1 jedis介绍 Redis不仅是使用命令来操作,现在基本上主流的语言都有客户端支持,比如java.C.C#.C++.php.Node.js.Go等. 在官方网站里列一些Java的客户端,有 ...
- 85)PHP,PHP处理mysql的函数种类
首先,就我知道的,一共有三种: 自己用过的是mysql和mysqli,还没用过PDO_mysql 有时,随着我们的各种东西版本的更新,会遇到某一个扩展用不了的情形,所以,就有了编写完成相同功能的使用不 ...
- Linux下安装mysql(yun方式)
1.进入下载好的mysql版本 cd /usr/local/mysql 2.解压安装包 tar -xzvf mysql-5.7.11.tar.gz 3.改名 直接改或者 mv 文件名 要改的文件名m ...
- asp.net---jquery--ajax 实现滚动条滚动到底部分页显示
前台:aspx页面 var bgtime = $(" #date1 ").val(); var overtime = $(" #date2 ").val(); ...
- django框架基础-ORM跨表操作-长期维护
############### 一对一跨表查询 ################ import os if __name__ == '__main__': os.environ.setde ...