环境
操作系统:CentOS 6.8 64位
Python版本: Python3.4.1
Python模块:Numpy,csv,time
原理
BP网络模型处理信息的基本原理是:输入信号Xi通过中间节点(隐层点)作用于输出节点,经过非线形变换,产生输出信号Yk,网络训练的每个样本包括输入向量X和期望输出量t,网络输出值Y与期望输出值t之间的偏差,通过调整输入节点与隐层节点的联接强度取值Wij和隐层节点与输出节点之间的联接强度Tjk以及阈值,使误差沿梯度方向下降,经过反复学习训练,确定与最小误差相对应的网络参数(权值和阈值),训练即告停止。此时经过训练的神经网络即能对类似样本的输入信息,自行处理输出误差最小的经过非线形转换的信息。
数据
根据题目描述,手写数字是28 * 28的图片数据,每一张图片的像素共 784个(28*28),将像素矩阵展开成一维,即为我们看到的csv格式的数据集。
训练集train.csv,第一行为label,最后一列为该行像素表示的数字(0~9)
测试集test.csv,第一行为label,第一列为ImageID,后续列为图片的一维像素值
数据处理
读取csv格式的训练数据集
将数据集的第一行删除
分离训练集的train_data和label部分
将train_data进行归一化处理,并转换成int型
代码实现
#导入训练数据
def LoadTrainData():
TrainDataList = []
print("......LoadTrainData......")
with open('train.csv') as file:
lines = csv.reader(file)
for line in lines:
TrainDataList.append(line)
TrainDataList.remove(TrainDataList[0]) #去掉第一行
TrainDataList = np.array(TrainDataList) #转换成数组
TrainDataLabels = TrainDataList[:,0] #提取最后一列
TrainData = TrainDataList[:,1:] #提取其余列
#Data 42000*784 label 1*42000
return toNorm(toInt(TrainData)),toInt(TrainDataLabels)
#导入测试数据
def LoadTestData():
TestDataList =[]
with open('test.csv') as file:
lines = csv.reader(file)
for line in lines:
TestDataList.append(line)
TestDataList.remove(TestDataList[0]) #删除数据集第一行
TestData = np.array(TestDataList)
return toNorm(toInt(TestData))
#转换成整形
def toInt(array):
matrix = np.mat(array)
m,n = np.shape(matrix)
newArray = np.zeros((m,n))
for i in range(m):
for j in range(n):
newArray[i,j] = int(matrix[i,j])
return newArray
#数据归一化处理
def autoNorm(array):
m,n = np.shape(array)
for i in range(m):
for j in range(n):
if array[i,j] != 0:
array[i,j] = 1
return array
神经网络训练
权重,偏置初始化
神经网络各层神经元数目初始化
学习效率设置
神经网络前向过程(sigmoid函数)
神经网络后向过程(梯度下降)
更新权重和偏置
代码实现
#训练神经网络
def TrainNetwork(sample,label):
sample_num = len(sample)
sample_len = len(sample[0])
out_num =10 #输出层
hid_num = 32 #隐藏层
w1 = 0.2*np.random.random((sample_len,hid_num))-0.1 #输入到隐藏层权重
w2 = 0.2*np.random.random((hid_num,out_num))-0.1 #隐藏到输出层权重
hid_offset = np.zeros(hid_num)
out_offset = np.zeros(out_num)
input_learnrate = 0.2
hid_learnrate = 0.1
for m in range(20): #迭代次数
for i in range(0,sample_num):
t_lable = np.zeros(out_num)
t_lable[int(label[0][i])]=1
#前向过程
hid_value = np.dot(sample[i],w1)+hid_offset
hid_act = sigmoid(hid_value)
out_value = np.dot(hid_act,w2)+out_offset
out_act = sigmoid(out_value)
#后向过程
err = t_lable - out_act #误差计算
#梯度下降
out_delta = err*out_act*(1-out_act)
hid_delta = hid_act*(1-hid_act)*np.dot(w2,out_delta)
#权重更新
for j in range(0,out_num):
w2[:,j]+=hid_learnrate*out_delta[j]*hid_act
for k in range(0,hid_num):
w1[:,k]+=input_learnrate*hid_delta[k]*sample[i]
#偏置更新
out_offset +=hid_learnrate * out_delta
hid_offset +=input_learnrate *hid_delta
return w1,w2,hid_offset,out_offset
预测
将权重,偏置带入,进行前向过程
预测神经网络的输出值,其输出的最大值索引即为最后结果
结果存储
代码实现
def test():
train_sample,train_label = LoadTrainData() #训练数据
w1,w2,hid,out = TrainNetwork(train_sample,train_label) #训练后的权重
print("训练完毕")
test_data = LoadTestData() #测试数据
print("测试文件导入完毕")
#前向过程
hid_result = np.dot(test_data,w1)+hid
hid_act_result = sigmoid(hid_result)
out_result = np.dot(hid_act_result,w2)+out
out_act_result = sigmoid(out_result)
result = []
imageid = []
#预测输出的最大值索引即为最后结果
for i in range(len(out_act_result[:,0])):
p = np.argmax(out_act_result[i])
number = i+1
imageid.append(number)
result.append(p)
saveResult(result,imageid)
print("结果存储完毕")
#存储结果
def saveResult(result,imageid):
with open('result.csv','w',encoding='utf8',newline='') as myfile:
myWriter = csv.writer(myfile)
myWriter.writerow(["ImageId","Label"])
for i in range(len(result)):
tmp = []
tmp.append(imageid[i])
tmp.append(result[i])
myWriter.writerow(tmp)