背景:上一篇使用tensorflow实现神经网络,其中框架已封装好了一些知识点(如误差逆传播),不利于初学者理解。为更直观的展示神经网络算法本身,本篇不使用tensorflow,以基本的python代码,实现上一篇中的气温预测实例。大家可对比下两篇的差异,理解算法的同时,体会下tensorflow框架。(tensorflow实现https://blog.csdn.net/MrMaurice/article/details/90031937)
代码功能:对山东某地区历史温度数据进行BP神经网络训练,通过前三小时温度数据,预测第四小时温度值。
数据来源:2016年4月份山东某地区温度数据,共30*24小时。1日到20日(20*24小时)数据为训练数据集,21到30日(10*24小时)数据为测试数据集。
选用典型的三层神经网路(输入层+一层隐含层+输出层),节点数设置为3-7-1,详细参数见程序:
d=3#输入节点个数
l=1#输出节点个数
q=2*d+1#隐层个数,采用经验公式2d+1
eta=0.5#学习率
error=0.002#精度
train_num=480#训练数据个数
test_num=240#测试数据个数
输入层到隐含层的权值为w1,矩阵大小为d*q;隐含层到输出层的权值为w2,矩阵大小为q*l;隐含层阈值为b1,输出层阈值为b2。
w1=[[random.random() for i in range(q)] for j in range(d)]
w2=[[random.random() for i in range(l)] for j in range(q)]
b1=[random.random() for i in range(q)]
b2=[random.random() for i in range(l)]
通过csv文件读取数据,并将网络的输入输出数据分组。csv文件数据排列为30*24行一列。文件链接:链接: https://pan.baidu.com/s/1-15ajI4TQI4pfKOqMTo0KA 提取码: 6ybg
dataset = pd.read_csv('tem.csv', delimiter=",")
dataset=np.array(dataset)
m,n=np.shape(dataset)
totalX=np.zeros((m-d,d))
totalY=np.zeros((m-d,l))
for i in range(m-d):#分组:前三个值输入,第四个值输出
totalX[i][0]=dataset[i][0]
totalX[i][1]=dataset[i+1][0]
totalX[i][2]=dataset[i+2][0]
totalY[i][0]=dataset[i+3][0]
将数据归一化到0-1内,并截取1-20日数据放到训练集,21-30日数据放到测试集。
#归一化数据
Normal_totalX=np.zeros((m-d,d))
Normal_totalY=np.zeros((m-d,l))
nummin=np.min(dataset)
nummax=np.max(dataset)
dif=nummax-nummin
for i in range(m-d):
for j in range(d):
Normal_totalX[i][j]=(totalX[i][j]-nummin)/dif
Normal_totalY[i][0]=(totalY[i][0]-nummin)/dif
#截取训练数据
trainX=Normal_totalX[:train_num-d,:]#训练数据
trainY=Normal_totalY[:train_num-d,:]
testX=Normal_totalX[train_num:,:]#测试数据
testY=Normal_totalY[train_num:,:]
m,n=np.shape(trainX)
import math
def sigmoid(iX):
for i in range(len(iX)):
iX[i] = 1 / (1 + math.exp(-iX[i]))
return iX
采用梯度下降法
#网络训练
start = time.clock()#起始时间
iter=0
while True:
sumE=0
for i in range(m):#每行循环
alpha=np.dot(trainX[i],w1)
b=sigmoid(alpha-b1)
beta=np.dot(b,w2)
predictY=sigmoid(beta-b2)
E = (predictY-trainY[i])*(predictY-trainY[i])
sumE+=E
#梯度下降法
g=predictY*(1-predictY)*(trainY[i]-predictY)
e=b*(1-b)*((np.dot(w2,g.T)).T)
w2+=eta*np.dot(b.reshape((q,1)),g.reshape((1,l)))
b2-=eta*g
w1+=eta*np.dot(trainX[i].reshape((d,1)),e.reshape((1,q)))
b1-=eta*e
sumE=sumE/m
iter+=1
if iter % 10 == 0:#每训练10次,输出误差
print("第 %d 次训练后,误差为:%g" % (iter, sumE))
if sumE
求取测试集均方误差。
#测试,求均方根误差
m,n=np.shape(testX)
MSE=0
for i in range(m):
alpha = np.dot(testX[i],w1)
b=sigmoid(alpha-b1)
beta = np.dot(b,w2)
y=sigmoid(beta - b2)
testY[i]=testY[i]*dif+nummin#反归一化
y=y*dif+nummin
MSE=(y-testY[i])*(y-testY[i])+MSE
MSE=MSE/m
print("测试集均方误差:",MSE)
最后简单实现下预测。采用5月1日连续三小时温度,预测第4小时温度。
def predict(iX):
iX=(iX-nummin)/dif#归一化
alpha = np.dot(iX, w1)
b=sigmoid(alpha-b1)
beta = np.dot(b, w2)
predictY=sigmoid(beta - b2)
predictY=predictY*dif+nummin#反归一化
return predictY
XX=[18.3,17.4,16.7]
XX=np.array(XX)
print("[18.3,17.4,16.7]输入下,预测气温为:",predict(XX))
import pandas as pd
import numpy as np
import random
import time
#定义神经网络的参数
d=3#输入节点个数
l=1#输出节点个数
q=2*d+1#隐层个数,采用经验公式2d+1
eta=0.5#学习率
error=0.002#精度
train_num=480#训练数据个数
test_num=240#测试数据个数
#初始化权值阈值
w1=[[random.random() for i in range(q)] for j in range(d)]
w2=[[random.random() for i in range(l)] for j in range(q)]
b1=[random.random() for i in range(q)]
b2=[random.random() for i in range(l)]
#读取气温数据
dataset = pd.read_csv('tem.csv', delimiter=",")
dataset=np.array(dataset)
m,n=np.shape(dataset)
totalX=np.zeros((m-d,d))
totalY=np.zeros((m-d,l))
for i in range(m-d):#分组:前三个值输入,第四个值输出
totalX[i][0]=dataset[i][0]
totalX[i][1]=dataset[i+1][0]
totalX[i][2]=dataset[i+2][0]
totalY[i][0]=dataset[i+3][0]
#归一化数据
Normal_totalX=np.zeros((m-d,d))
Normal_totalY=np.zeros((m-d,l))
nummin=np.min(dataset)
nummax=np.max(dataset)
dif=nummax-nummin
for i in range(m-d):
for j in range(d):
Normal_totalX[i][j]=(totalX[i][j]-nummin)/dif
Normal_totalY[i][0]=(totalY[i][0]-nummin)/dif
#截取训练数据
trainX=Normal_totalX[:train_num-d,:]#训练数据
trainY=Normal_totalY[:train_num-d,:]
testX=Normal_totalX[train_num:,:]#测试数据
testY=Normal_totalY[train_num:,:]
m,n=np.shape(trainX)
#实现sigmoid函数
import math
def sigmoid(iX):
for i in range(len(iX)):
iX[i] = 1 / (1 + math.exp(-iX[i]))
return iX
#网络训练
start = time.clock()#起始时间
iter=0
while True:
sumE=0
for i in range(m):#每行循环
alpha=np.dot(trainX[i],w1)
b=sigmoid(alpha-b1)
beta=np.dot(b,w2)
predictY=sigmoid(beta-b2)
E = (predictY-trainY[i])*(predictY-trainY[i])
sumE+=E
#梯度下降法
g=predictY*(1-predictY)*(trainY[i]-predictY)
e=b*(1-b)*((np.dot(w2,g.T)).T)
w2+=eta*np.dot(b.reshape((q,1)),g.reshape((1,l)))
b2-=eta*g
w1+=eta*np.dot(trainX[i].reshape((d,1)),e.reshape((1,q)))
b1-=eta*e
sumE=sumE/m
iter+=1
if iter % 10 == 0:#每训练10次,输出误差
print("第 %d 次训练后,误差为:%g" % (iter, sumE))
if sumE