环境:
ipython notebook
第一章 数学知识
人工智能探讨的就是 求解图像识别 的问题
关键点:
- 所有有用的计算机系统都有一个输入和一个输出,并在输入和输出之间进行某种类型的计算。
- 当我们不能精确指导一些事情如何运作时,我们可以尝试使用 模型 来估计其运作方式,在模型中,包括了我们可以调整的参数。如果我们不知道如何将千米转换成英里,那么我们可以使用线性函数作为模型,并使用可调节的梯度值作为参数。
- 改进这些模型的一种好方法是,基于模型和已知真实示例之间的比较,得到模型偏移的误差值,调整参数。
训练器:接受一个输入,并做出应有的预测,输出结果
训练数据:用来训练预测器活着分类器的真实实例
1. 误差计算
误差E = 期望的正确值 - 基于A的猜测值, A代表 随机给定的参数
即,训练数据所给出的正确答案和实际输出之间的差值。
改进
注意⚠️:
- 使用朴素的调整方法会出现一个问题,即改进后的模型只与最后一次训练样本最匹配,“有效地”忽略了所有以前的训练样本。解决这个问题的一种好方法是使用学习率,调整改进速率,这样单一的训练样本就不能主导整个学习过程。
- 真实世界的训练样本可能充满噪声或者包含错误,适度更新有助于限制这些错误样本的影响。
线性分类器解决不了大多数实际问题 -> 解决方案: 可使用多个线性分类器来划分由单一直线无法分离的数据。
神经网络的核心思想:多个分类器一起工作
2. 激活函数
只有输入超过一定阈值(threshold),才能产生输出。
阈值:利用激活函数实现
S函数:sigmoid function:%22%20aria-hidden%3D%22true%22%3E%0A%20%3Cuse%20xlink%3Ahref%3D%22%23E1-MJMATHI-79%22%20x%3D%220%22%20y%3D%220%22%3E%3C%2Fuse%3E%0A%20%3Cuse%20xlink%3Ahref%3D%22%23E1-MJMAIN-3D%22%20x%3D%22775%22%20y%3D%220%22%3E%3C%2Fuse%3E%0A%3Cg%20transform%3D%22translate(1553%2C0)%22%3E%0A%3Cg%20transform%3D%22translate(397%2C0)%22%3E%0A%3Crect%20stroke%3D%22none%22%20width%3D%223365%22%20height%3D%2260%22%20x%3D%220%22%20y%3D%22220%22%3E%3C%2Frect%3E%0A%20%3Cuse%20xlink%3Ahref%3D%22%23E1-MJMAIN-31%22%20x%3D%221432%22%20y%3D%22676%22%3E%3C%2Fuse%3E%0A%3Cg%20transform%3D%22translate(60%2C-722)%22%3E%0A%20%3Cuse%20xlink%3Ahref%3D%22%23E1-MJMAIN-31%22%20x%3D%220%22%20y%3D%220%22%3E%3C%2Fuse%3E%0A%20%3Cuse%20xlink%3Ahref%3D%22%23E1-MJMAIN-2B%22%20x%3D%22722%22%20y%3D%220%22%3E%3C%2Fuse%3E%0A%3Cg%20transform%3D%22translate(1723%2C0)%22%3E%0A%20%3Cuse%20xlink%3Ahref%3D%22%23E1-MJMATHI-65%22%20x%3D%220%22%20y%3D%220%22%3E%3C%2Fuse%3E%0A%3Cg%20transform%3D%22translate(466%2C288)%22%3E%0A%20%3Cuse%20transform%3D%22scale(0.707)%22%20xlink%3Ahref%3D%22%23E1-MJMAIN-2212%22%20x%3D%220%22%20y%3D%220%22%3E%3C%2Fuse%3E%0A%20%3Cuse%20transform%3D%22scale(0.707)%22%20xlink%3Ahref%3D%22%23E1-MJMATHI-78%22%20x%3D%22778%22%20y%3D%220%22%3E%3C%2Fuse%3E%0A%3C%2Fg%3E%0A%3C%2Fg%3E%0A%3C%2Fg%3E%0A%3C%2Fg%3E%0A%3C%2Fg%3E%0A%3C%2Fg%3E%0A%3C%2Fsvg%3E#card=math&code=y%20%3D%20%5Cfrac%7B1%7D%7B1%2Be%5E%7B-x%7D%7D&id=F3X4y)

对所有输入进行相加操作,得到最终总和,然后作为S函数的输入,最后输出结果。
注意:只有总和超过阈值,才能输出结果。

神经网络通过调整优化网络内部的链接权重改进输出,一些权重可能会变为0或者接近于0.
3. 输出计算
利用 矩阵 进行神经网络计算 更高效 -> 神经网络向前馈送信号所需的大量计算可以表示为矩阵乘法,即点乘。
适用于前后层之间的计算
W:权重矩阵; I:输入矩阵, X:组合调节后的信号,即输入到第二层的结果矩阵
注意⚠️:权重矩阵在前,输入矩阵在后。
O: 表示矩阵,包含了来自神经网络的最后一层中的所有输出
4. 权重更新
反向传播:使用权重将误差从输出向后传播到网络中。 -> 每个链接对误差造成的贡献不一样。
计算过程

注意⚠️ :两处地方使用了权重
- 将信号从输入向前传播到输出层;
- 将误差从输出向后传播到网络中。
关键点:
- 梯度下降法 是求解函数最小值的一种很好的办法,当函数非常复杂困难,并且不能轻易使用数学代数求解函数时,这种方法就发挥了很好的作用。
- 更重要的是,当函数有很多参数,一些其他方法不切实际,或者会得出错误答案,这种方法依然可以适用。
- 这种方法也具有弹性,可以容忍不完善的数据,如果我们不能完美地描述函数,或者我们偶尔错了一步,也不会错的很离谱。
误差函数斜率
用于输入层和隐藏层之间的权重调整
代表误差(目标值-实际值)==> 隐藏层节点中重组的向后传播误差。
内部求和表达式指的是前一层,so,求和范围是所有由权重调节的进去隐藏层节点j的输入。
第一层节点的输出
权重改变的方向和梯度相反
结合上两个公式可得 ==>
第二章 python实现神经网络
使用ipython实现
在terminal中输入 ipython notebook 即可打开jupter
1. 基础知识
# numpy : 包含一些有用的工具(数组)以及使用这些工具进行计算# matplotlib.pyplot : 可绘制图形# %matplotlib inline : 在notebook上绘制图形,不要另外窗口绘制# imshow() : 创建绘图第一个参数 : 代表要绘制的数组第二个参数 : 不要为了让绘图看起来更加平滑而混合颜色
案例代码:
import numpya = numpy.zeros([3,2])a[0,0] = 4a[0,1] = 2a[1,0] = 9a[2,1] = 12import matplotlib.pyplot%matplotlib inlinematplotlib.pyplot.imshow(a, interpolation='nearest')
案例效果图:
2. 使用python进行diy
import numpyimport scipy.special# 创建一个神经网络类class neuralNetwork:# 初始化神经网络def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):self.inodes = inputnodes # 输入层节点self.hnodes = hiddennodes # 隐藏层节点self.onodes = outputnodes # 输出层节点self.lr = learningrate # 学习率# 输入+隐藏 隐藏+输出 这两个权重矩阵self.wih = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))self.who = numpy.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):# 1. 针对给定的训练样本计算输出# 将输入数据转化成numpy数组, 维度起码是2维的 最后进行转置inputs = numpy.array(inputs_list, ndmin=2).Ttargets = numpy.array(targets_list, ndmin=2).T# numpy.dot 矩阵乘法hidden_inputs = numpy.dot(self.wih, inputs)hidden_outputs = self.activation_function(hidden_inputs)final_inputs = numpy.dot(self.who, hidden_outputs)final_outputs = self.activation_function(final_inputs)# 2. 将计算得到的输出与所需输出进行对比,使用差值指导网络权重更新output_errors = targets - final_outputshidden_errors = numpy.dot(self.who.T, output_errors)# numpy.transpose == .Tself.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))pass# 返回网络输出def query(self, inputs_list):inputs = numpy.array(inputs_list, ndmin=2).Thidden_inputs = numpy.dot(self.wih, inputs)hidden_outputs = self.activation_function(hidden_inputs)final_inputs = numpy.dot(self.who, hidden_outputs)final_outputs = self.activation_function(final_inputs)return final_outputs
3. 手写数字案例
# 环境import numpyimport scipy.specialimport matplotlib.pyplot%matplotlib inline# 神经网络训练函数class neuralNetwork:def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):self.inodes = inputnodesself.hnodes = hiddennodesself.onodes = outputnodesself.lr = learningrateself.wih = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))self.who = numpy.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))self.activation_function = lambda x:scipy.special.expit(x)passdef train(self, inputs_list, targets_list):inputs = numpy.array(inputs_list, ndmin=2).Ttargets = numpy.array(targets_list, ndmin=2).Thidden_inputs = numpy.dot(self.wih, inputs)hidden_outputs = self.activation_function(hidden_inputs)final_inputs = numpy.dot(self.who, hidden_outputs)final_outputs = self.activation_function(final_inputs)output_errors = targets - final_outputshidden_errors = numpy.dot(self.who.T, output_errors)self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))passdef query(self, inputs_list):inputs = numpy.array(inputs_list, ndmin=2).Thidden_inputs = numpy.dot(self.wih, inputs)hidden_outputs = self.activation_function(hidden_inputs)final_inputs = numpy.dot(self.who, hidden_outputs)final_outputs = self.activation_function(final_inputs)return final_outputs# 训练函数的一些基本数据input_nodes = 784hidden_nodes = 200 # 隐藏层节点最好的方法是进行实验然后找到最合适的节点数output_nodes = 10learning_rate = 0.15n = neuralNetwork(input_nodes,hidden_nodes,output_nodes, learning_rate)# 训练数据training_data_file = open("mnist_dataset/mnist_train.csv", 'r')training_data_list = training_data_file.readlines()training_data_file.close()# 训练网络 一个epoch 即网络只训练一次for record in training_data_list:all_values = record.split(',')inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01targets = numpy.zeros(output_nodes)+0.01targets[int(all_values[0])] = 0.99n.train(inputs, targets)pass# 准备测试数据test_data_file = open("mnist_dataset/mnist_test.csv", 'r')test_data_list = test_data_file.readlines()test_data_file.close()# 测试神经网络scorecard = []for record in test_data_list:all_values = record.split(',')correct_label = int(all_values[0])inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01outputs = n.query(inputs)# 找到输出值当中的最大值,并返回所在位置label = numpy.argmax(outputs)# 如果值相等,则在数组中添加元素1,否则添加元素0if (label == correct_label):scorecard.append(1)else:scorecard.append(0)pass# 得分比例scorecard_array = numpy.asarray(scorecard)print("performance = ", scorecard_array.sum() / scorecard_array.size)
4. 优化方向
- 学习率
- 训练次数 epoch
- 改变神经网络形状 -> 隐藏层节点个数 (隐藏层节点前后的链接权重具有学习能力)
学习率 和 epoch组合进行多次实验,得到最优结果,可尽量减少在梯度下降过程中随机性的影响
第三章 神经网络升级
特定的神经网络架构:
- 每一层节点数目的选择
- 隐藏层的选择
- 激活函数的选择
旋转角度可增加数据
对于最大化附加数据的价值,10度是最佳角度
