我爱编程Python&机器学习&神经网络

基于python的BP神经网络——kaggle手写数字识别

2018-04-11  本文已影响0人  王_呵呵

环境

操作系统:CentOS 6.8 64位
Python版本: Python3.4.1
Python模块:Numpy,csv,time

原理

BP网络模型处理信息的基本原理是:输入信号Xi通过中间节点(隐层点)作用于输出节点,经过非线形变换,产生输出信号Yk,网络训练的每个样本包括输入向量X和期望输出量t,网络输出值Y与期望输出值t之间的偏差,通过调整输入节点与隐层节点的联接强度取值Wij和隐层节点与输出节点之间的联接强度Tjk以及阈值,使误差沿梯度方向下降,经过反复学习训练,确定与最小误差相对应的网络参数(权值和阈值),训练即告停止。此时经过训练的神经网络即能对类似样本的输入信息,自行处理输出误差最小的经过非线形转换的信息。

详细原理转BP神经网络原理

数据

数据集:Digit Recognizer

根据题目描述,手写数字是28 * 28的图片数据,每一张图片的像素共 784个(28*28),将像素矩阵展开成一维,即为我们看到的csv格式的数据集。

训练集train.csv,第一行为label,最后一列为该行像素表示的数字(0~9)
测试集test.csv,第一行为label,第一列为ImageID,后续列为图片的一维像素值

数据处理

  1. 读取csv格式的训练数据集
  2. 将数据集的第一行删除
  3. 分离训练集的train_data和label部分
  4. 将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

神经网络训练

  1. 权重,偏置初始化
  2. 神经网络各层神经元数目初始化
  3. 学习效率设置
  4. 神经网络前向过程(sigmoid函数)
  5. 神经网络后向过程(梯度下降)
  6. 更新权重和偏置

代码实现

#训练神经网络
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

预测

  1. 将权重,偏置带入,进行前向过程
  2. 预测神经网络的输出值,其输出的最大值索引即为最后结果
  3. 结果存储

代码实现

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)
上一篇 下一篇

猜你喜欢

热点阅读