环境:

  1. ipython notebook

示例:www.epubit.com

第一章 数学知识

人工智能探讨的就是 求解图像识别 的问题

关键点:

  1. 所有有用的计算机系统都有一个输入和一个输出,并在输入和输出之间进行某种类型的计算。
  2. 当我们不能精确指导一些事情如何运作时,我们可以尝试使用 模型 来估计其运作方式,在模型中,包括了我们可以调整的参数。如果我们不知道如何将千米转换成英里,那么我们可以使用线性函数作为模型,并使用可调节的梯度值作为参数。
  3. 改进这些模型的一种好方法是,基于模型和已知真实示例之间的比较,得到模型偏移的误差值,调整参数

训练器:接受一个输入,并做出应有的预测,输出结果
训练数据:用来训练预测器活着分类器的真实实例

1. 误差计算

误差E = 期望的正确值 - 基于A的猜测值, A代表 随机给定的参数

即,训练数据所给出的正确答案和实际输出之间的差值

《Python神经网络编程》 - 图1 《Python神经网络编程》 - 图2

改进

《Python神经网络编程》 - 图3 《Python神经网络编程》 - 图4

注意⚠️:

  1. 使用朴素的调整方法会出现一个问题,即改进后的模型只与最后一次训练样本最匹配,“有效地”忽略了所有以前的训练样本。解决这个问题的一种好方法是使用学习率,调整改进速率,这样单一的训练样本就不能主导整个学习过程。
  2. 真实世界的训练样本可能充满噪声或者包含错误,适度更新有助于限制这些错误样本的影响。

线性分类器解决不了大多数实际问题 -> 解决方案: 可使用多个线性分类器来划分由单一直线无法分离的数据。

神经网络的核心思想:多个分类器一起工作

2. 激活函数

只有输入超过一定阈值(threshold),才能产生输出。

阈值:利用激活函数实现

S函数:sigmoid function:
《Python神经网络编程》 - 图5%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)

image.png

对所有输入进行相加操作,得到最终总和,然后作为S函数的输入,最后输出结果

注意:只有总和超过阈值,才能输出结果。

image.png
神经网络通过调整优化网络内部的链接权重改进输出,一些权重可能会变为0或者接近于0.

3. 输出计算

利用 矩阵 进行神经网络计算 更高效 -> 神经网络向前馈送信号所需的大量计算可以表示为矩阵乘法,即点乘。

《Python神经网络编程》 - 图8 适用于前后层之间的计算

W:权重矩阵; I:输入矩阵, X:组合调节后的信号,即输入到第二层的结果矩阵
注意⚠️:权重矩阵在前,输入矩阵在后

《Python神经网络编程》 - 图9

O: 表示矩阵,包含了来自神经网络的最后一层中的所有输出

4. 权重更新

反向传播:使用权重将误差从输出向后传播到网络中。 -> 每个链接对误差造成的贡献不一样。

计算过程
image.png

image.png

注意⚠️ :两处地方使用了权重

  1. 将信号从输入向前传播到输出层;
  2. 将误差从输出向后传播到网络中。

关键点:

  1. 梯度下降法 求解函数最小值的一种很好的办法,当函数非常复杂困难,并且不能轻易使用数学代数求解函数时,这种方法就发挥了很好的作用。
  2. 更重要的是,当函数有很多参数,一些其他方法不切实际,或者会得出错误答案,这种方法依然可以适用。
  3. 这种方法也具有弹性,可以容忍不完善的数据,如果我们不能完美地描述函数,或者我们偶尔错了一步,也不会错的很离谱。

误差函数斜率

用于输入层和隐藏层之间的权重调整

《Python神经网络编程》 - 图12

《Python神经网络编程》 - 图13代表误差(目标值-实际值)==> 隐藏层节点中重组的向后传播误差。
《Python神经网络编程》 - 图14内部求和表达式指的是前一层,so,求和范围是所有由权重调节的进去隐藏层节点j的输入
《Python神经网络编程》 - 图15第一层节点的输出

权重改变的方向和梯度相反

《Python神经网络编程》 - 图16

《Python神经网络编程》 - 图17

结合上两个公式可得 ==> 《Python神经网络编程》 - 图18

第二章 python实现神经网络

使用ipython实现

在terminal中输入 ipython notebook 即可打开jupter

1. 基础知识

  1. # numpy : 包含一些有用的工具(数组)以及使用这些工具进行计算
  2. # matplotlib.pyplot : 可绘制图形
  3. # %matplotlib inline : 在notebook上绘制图形,不要另外窗口绘制
  4. # imshow() : 创建绘图
  5. 第一个参数 : 代表要绘制的数组
  6. 第二个参数 : 不要为了让绘图看起来更加平滑而混合颜色

案例代码:

  1. import numpy
  2. a = numpy.zeros([3,2])
  3. a[0,0] = 4
  4. a[0,1] = 2
  5. a[1,0] = 9
  6. a[2,1] = 12
  7. import matplotlib.pyplot
  8. %matplotlib inline
  9. matplotlib.pyplot.imshow(a, interpolation='nearest')

案例效果图:
image.png

2. 使用python进行diy

  1. import numpy
  2. import scipy.special
  3. # 创建一个神经网络类
  4. class neuralNetwork:
  5. # 初始化神经网络
  6. def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
  7. self.inodes = inputnodes # 输入层节点
  8. self.hnodes = hiddennodes # 隐藏层节点
  9. self.onodes = outputnodes # 输出层节点
  10. self.lr = learningrate # 学习率
  11. # 输入+隐藏 隐藏+输出 这两个权重矩阵
  12. self.wih = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))
  13. self.who = numpy.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))
  14. # 激活函数
  15. self.activation_function = lambda x:scipy.special.expit(x)
  16. pass
  17. # 训练神经网络
  18. def train(self, inputs_list, targets_list):
  19. # 1. 针对给定的训练样本计算输出
  20. # 将输入数据转化成numpy数组, 维度起码是2维的 最后进行转置
  21. inputs = numpy.array(inputs_list, ndmin=2).T
  22. targets = numpy.array(targets_list, ndmin=2).T
  23. # numpy.dot 矩阵乘法
  24. hidden_inputs = numpy.dot(self.wih, inputs)
  25. hidden_outputs = self.activation_function(hidden_inputs)
  26. final_inputs = numpy.dot(self.who, hidden_outputs)
  27. final_outputs = self.activation_function(final_inputs)
  28. # 2. 将计算得到的输出与所需输出进行对比,使用差值指导网络权重更新
  29. output_errors = targets - final_outputs
  30. hidden_errors = numpy.dot(self.who.T, output_errors)
  31. # numpy.transpose == .T
  32. self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))
  33. self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))
  34. pass
  35. # 返回网络输出
  36. def query(self, inputs_list):
  37. inputs = numpy.array(inputs_list, ndmin=2).T
  38. hidden_inputs = numpy.dot(self.wih, inputs)
  39. hidden_outputs = self.activation_function(hidden_inputs)
  40. final_inputs = numpy.dot(self.who, hidden_outputs)
  41. final_outputs = self.activation_function(final_inputs)
  42. return final_outputs

3. 手写数字案例

  1. # 环境
  2. import numpy
  3. import scipy.special
  4. import matplotlib.pyplot
  5. %matplotlib inline
  6. # 神经网络训练函数
  7. class neuralNetwork:
  8. def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
  9. self.inodes = inputnodes
  10. self.hnodes = hiddennodes
  11. self.onodes = outputnodes
  12. self.lr = learningrate
  13. self.wih = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))
  14. self.who = numpy.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))
  15. self.activation_function = lambda x:scipy.special.expit(x)
  16. pass
  17. def train(self, inputs_list, targets_list):
  18. inputs = numpy.array(inputs_list, ndmin=2).T
  19. targets = numpy.array(targets_list, ndmin=2).T
  20. hidden_inputs = numpy.dot(self.wih, inputs)
  21. hidden_outputs = self.activation_function(hidden_inputs)
  22. final_inputs = numpy.dot(self.who, hidden_outputs)
  23. final_outputs = self.activation_function(final_inputs)
  24. output_errors = targets - final_outputs
  25. hidden_errors = numpy.dot(self.who.T, output_errors)
  26. self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))
  27. self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))
  28. pass
  29. def query(self, inputs_list):
  30. inputs = numpy.array(inputs_list, ndmin=2).T
  31. hidden_inputs = numpy.dot(self.wih, inputs)
  32. hidden_outputs = self.activation_function(hidden_inputs)
  33. final_inputs = numpy.dot(self.who, hidden_outputs)
  34. final_outputs = self.activation_function(final_inputs)
  35. return final_outputs
  36. # 训练函数的一些基本数据
  37. input_nodes = 784
  38. hidden_nodes = 200 # 隐藏层节点最好的方法是进行实验然后找到最合适的节点数
  39. output_nodes = 10
  40. learning_rate = 0.15
  41. n = neuralNetwork(input_nodes,hidden_nodes,output_nodes, learning_rate)
  42. # 训练数据
  43. training_data_file = open("mnist_dataset/mnist_train.csv", 'r')
  44. training_data_list = training_data_file.readlines()
  45. training_data_file.close()
  46. # 训练网络 一个epoch 即网络只训练一次
  47. for record in training_data_list:
  48. all_values = record.split(',')
  49. inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
  50. targets = numpy.zeros(output_nodes)+0.01
  51. targets[int(all_values[0])] = 0.99
  52. n.train(inputs, targets)
  53. pass
  54. # 准备测试数据
  55. test_data_file = open("mnist_dataset/mnist_test.csv", 'r')
  56. test_data_list = test_data_file.readlines()
  57. test_data_file.close()
  58. # 测试神经网络
  59. scorecard = []
  60. for record in test_data_list:
  61. all_values = record.split(',')
  62. correct_label = int(all_values[0])
  63. inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
  64. outputs = n.query(inputs)
  65. # 找到输出值当中的最大值,并返回所在位置
  66. label = numpy.argmax(outputs)
  67. # 如果值相等,则在数组中添加元素1,否则添加元素0
  68. if (label == correct_label):
  69. scorecard.append(1)
  70. else:
  71. scorecard.append(0)
  72. pass
  73. # 得分比例
  74. scorecard_array = numpy.asarray(scorecard)
  75. print("performance = ", scorecard_array.sum() / scorecard_array.size)

4. 优化方向

  1. 学习率
  2. 训练次数 epoch
  3. 改变神经网络形状 -> 隐藏层节点个数 (隐藏层节点前后的链接权重具有学习能力)

学习率 和 epoch组合进行多次实验,得到最优结果,可尽量减少在梯度下降过程中随机性的影响

第三章 神经网络升级

特定的神经网络架构:

  1. 每一层节点数目的选择
  2. 隐藏层的选择
  3. 激活函数的选择

旋转角度可增加数据

对于最大化附加数据的价值,10度是最佳角度