{"cells":[{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"51733b51-f5bc-9e18-3720-68b4804b2e2a"},"outputs":[],"source":"#coding = utf-8\nimport math\nimport random\n\n__author__ = \"clogos\"\n\n'''Sigmoid函数及它的导数(deriv为真时为导数)'''\ndef sigmoid(x, deriv = False):\n\tif(deriv == True):\n\t\treturn x * (1 - x)\n\telse:\n\t\treturn 1.0 / (1.0 + math.exp(-x))\n\n'''定义BP网络的能量函数(误差函数)'''\ndef get_E(A, B, n):\n\tEp = 0\n\tfor i in range(n):\n\t\tEp += 0.5 * ((A[i] - B[i]) ** 2)\n\treturn Ep\n\n\n'''生成[a, b]之间的随机数'''\ndef rand(a, b):\n\treturn random.uniform(a, b)\n\n'''构造一个n * m的矩阵，并用fill填充'''\ndef creatMatrix(n, m, fill = 0.0):\n\tmat = []\n\tfor i in range(n):\n\t\tmat.append([fill] * m)\n\treturn mat\n\nclass BP:\n\n\t'''初始化BP神经网络'''\n\tdef __init__(self, I, J, K):\n\t\t'''输入层、隐含层、输出层的单元数分别是I、J和K'''\n\t\tself.nI = I\n\t\tself.nJ = J\n\t\tself.nK = K\n\n\t\t'''激活三层BP神经网络结构的所有节点'''\n\t\tself.nodeI = [1.0] * self.nI\n\t\tself.nodeJ = [1.0] * self.nJ\n\t\tself.nodeK = [1.0] * self.nK\n\n\t\t'''构建神经元权重'''\n\t\tself.Wij = creatMatrix(self.nI, self.nJ)\n\t\tself.Wjk = creatMatrix(self.nJ, self.nK)\n\n\t\t'''构建权重修正矩阵'''\n\t\tself.Cij = creatMatrix(self.nI, self.nJ)\n\t\tself.Cjk = creatMatrix(self.nJ, self.nK)\n\n\t\t'''权重初始化'''\n\t\tfor i in range(self.nI):\n\t\t\tfor j in range(self.nJ):\n\t\t\t\tself.Wij[i][j] = rand(0.1, 0.5)\n\t\tfor j in range(self.nJ):\n\t\t\tfor k in range(self.nK):\n\t\t\t\tself.Wjk[j][k] = rand(0.1, 0.5)\n\n\t'''第一阶段，正向传播'''\n\tdef predict(self, inputs):\n\t\t'''激活输入层'''\n\t\tfor i in range(self.nI):\n\t\t\tself.nodeI[i] = inputs[i]\n\n\t\t'''激活隐含层'''\n\t\tfor j in range(self.nJ):\n\t\t\tsumNet = 0.0\n\t\t\tfor i in range(self.nI):\n\t\t\t\tsumNet += self.Wij[i][j] * self.nodeI[i]\n\t\t\tself.nodeJ[j] = sigmoid(sumNet)\n\n\t\t'''激活输出层'''\n\t\tfor k in range(self.nK):\n\t\t\tsumNet = 0\n\t\t\tfor j in range(self.nJ):\n\t\t\t\tsumNet += self.Wjk[j][k] * self.nodeJ[j]\n\t\t\tself.nodeK[k] = sigmoid(sumNet)\n\n\t\treturn self.nodeK[:]\n\n\t'''第二阶段，反向传播'''\n\tdef backPropagate(self, targets, studySpeed, correct):\n\t\t'''计算输出层的误差'''\n\t\toutput_deltas = [0.0] * self.nK\n\t\tfor k in range(self.nK):\n\t\t\tdiff = targets[k] - self.nodeK[k]\n\t\t\toutput_deltas[k] = sigmoid(self.nodeK[k], True) * diff\n\n\t\t'''计算隐含层的误差'''\n\t\thidden_deltas = [0.0] * self.nJ\n\t\tfor j in range(self.nJ):\n\t\t\tdiff = 0.0\n\t\t\tfor k in range(self.nK):\n\t\t\t\tdiff += output_deltas[k] * self.Wjk[j][k]\n\t\t\thidden_deltas[j] = sigmoid(self.nodeJ[j], True) * diff\n\n\t\t'''修正输出层与隐含层之间的权重'''\n\t\tfor j in range(self.nJ):\n\t\t\tfor k in range(self.nK):\n\t\t\t\tdtW = output_deltas[k] * self.nodeJ[j]\n\t\t\t\tself.Wjk[j][k] += studySpeed * dtW\n#\t\t\t\tself.Wjk[j][k] += self.Cjk[j][k] * correct #考虑纠正率\n\t\t\t\tself.Cjk[j][k] = dtW\n\n\t\t'''修正隐含层与输入层之间的权重'''\n\t\tfor i in range(self.nI):\n\t\t\tfor j in range(self.nJ):\n\t\t\t\tdtW = hidden_deltas[j] * self.nodeI[i]\n\t\t\t\tself.Wij[i][j] += studySpeed * dtW\n#\t\t\t\tself.Wij[i][j] += self.Cij[i][j] * correct #考虑纠正率\n\t\t\t\tself.Cij[i][j] = dtW\n\n\t\t'''返回误差'''\n\t\treturn get_E(targets, self.nodeK, self.nK)\n\n\tdef train(self, patterns, iterations = 10000, studySpeed = 0.5, correct = 0.1, minx = 0.0001):\n\t\tfor i in range(iterations):\n\t\t\tnowError = 0.0\n\t\t\tfor item in patterns:\n\t\t\t\tinputs = item[0]\n\t\t\t\ttargets = item[1]\n\t\t\t\tself.predict(inputs)\n\t\t\t\tnowError += self.backPropagate(targets, studySpeed, correct)\n\t\t\t'''满足精度要求，终止学习'''\n            if(i % 100==0):\n                print(nowError)\n\t\t\tif(nowError < minx):\n            \tbreak\n\n\tdef test(self, patterns):\n\t\ttestResult = []\n\t\tfor item in patterns:\n\t\t\tresult = self.predict(item[0])\n#\t\t\tprint(item[0], '->', result, \"[target]\", item[1][0], \"[error]\", (item[1][0] - result[0]))\n\t\t\ttestResult.append([item[0], result])\n\t\treturn testResult[:]\n\n'''拟合的函数'''\ndef functionF(x):\n\tif(x <= 1):\n\t\treturn 0.5 + (0.5 / 1) * x\t\n\telif(x <= 3):\n\t\treturn 1.5 + (-1.0 / 2) * x\n\telse:\n\t \treturn -1.5 + (0.5 / 1) * x\n\n'''获取训练样本'''\ndef getTrainPattern(n, dt):\n\tpatterns = []\n\tx = 0.0\n\tfor i in range(n):\n\t\ty = functionF(x)\n\t\tpatterns.append([[x], [y]])\n\t\tx += dt \n\treturn patterns \n\n'''获取测试样本'''\ndef getTestPattern(n):\n\tpatterns = []\t\n\tfor i in range(n):\n\t\tx = rand(0, 4)\n\t\ty = functionF(x)\n\t\tpatterns.append([[x], [y]])\n\treturn patterns \n\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n'''把最终结果作图显示'''\ndef Drawing(trainPatterns, testPatterns):\n\ttestPatterns.sort()\n\txData1 = []\n\tyData1 = []\n\tfor x in trainPatterns:\n\t\txData1.extend(x[0])\n\t\tyData1.extend(x[1])\n\txData1 = np.array(xData1)\n\tyData1 = np.array(yData1)\n\txData2 = []\n\tyData2 = []\n\tfor x in testPatterns:\n\t\txData2.extend(x[0])\n\t\tyData2.extend(x[1])\n\txData2 = np.array(xData2)\n\tyData2 = np.array(yData2)\n\n\tplt.figure(num=1, figsize=(8, 6))\n\tplt.title('BP', size=14)\n\tplt.xlabel('x-axis', size=14)\n\tplt.ylabel('y-axis', size=14)\n\tplt.plot(xData1, yData1, color='b', linestyle='-', label='trainPatterns')\n\tplt.plot(xData2, yData2, color='r', linestyle='--', marker='o', label='testResult')\n\tplt.legend(loc='upper left')\n\tplt.savefig('BP.png', format='png')\n\n\ndef main():\n\ttrainPatterns = getTrainPattern(80, 0.05)\n\ttestPatterns = getTestPattern(100)\n\tbp = BP(1, 10, 1)\n\tbp.train(trainPatterns)\n\ttestResult = bp.test(testPatterns)\n\n\tDrawing(trainPatterns, testResult)\n\nif __name__ == \"__main__\":\n\tmain()"}],"metadata":{"_change_revision":0,"_is_fork":false,"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.0"}},"nbformat":4,"nbformat_minor":0}