使用python实现简单全连接神经网络

最近在学习神经网络的相关知识,特在此做一个笔记。

python语言的功能很强大,可以使用很少的代码实现很多功能,因此大家如果想研究深度学习的话,一定要懂得python语言。

这篇笔记记录我的第一次使用python编写神经网络代码的过程,其中代码基本是借鉴neural networks and deep learning上的知识,这本书对神经网络学习有很大帮助,浅显易懂的深入了CNN的知识,初学者可以研究一下。

好了,多的不说,直接上代码:

这里我做的是最简单的mnist手写字的识别,首先是数据库处理。

这里我下载了42028张mnist图片,每张图片大小是28*28,需要的可以到这里下载。

一般需要把数据转化为pkl文件,便于存储和以后的使用。

import os
import cPickle
import numpy
from PIL import Image
import commondata	#自己定义的文件,里面有一些公用的变量

dirname = 'train'		#图片根目录
myfile = 'train.pkl'		#生成的文件名称

number = 0			#图片个数
for filename in os.listdir(dirname):
    filename1 = dirname + '/' + filename
    for filename2 in os.listdir(filename1):
        number += 1				</span>

pictures = numpy.empty((number,commondata.ImageWidth*commondata.ImageHeight))	#图片文件
lables = numpy.empty(number)							#标签文件

index = 0
lable = 0

for filename in os.listdir(dirname):
    filename1 = dirname + '/' + filename
    for filename2 in os.listdir(filename1):
        filename2 = filename1 + '/' + filename2
        image = Image.open(filename2)
        image = image.convert('L')					#为了简便,先统一转化为灰度图片
        image = image.resize((commondata.ImageHeight,commondata.ImageWidth))
        image_narray = numpy.asarray(image,dtype = 'float64')/256
        pictures[index] = numpy.ndarray.flatten(image_narray)
        lables[index] = lable
        index = index + 1
    lable = lable + 1

lables = lables.astype(numpy.int)
write_file=open(myfile,'wb')
cPickle.dump([pictures[:],lables[:]],write_file,-1)
write_file.close()
运行此代码,可以生成一个名字为train.pkl的文件,然后更改根目录和生成文件的名称可以得到test.pkl


生成文件后,还需要调用此文件:

import cPickle
import numpy as np
import commondata

NumClass = commondata.NumClass
ImageWidth = commondata.ImageWidth
ImageHeight = commondata.ImageHeight

def vectorized_result(j):
    e = np.zeros((NumClass,1))
    e[j] = 1.0
    return e
    
def load_data():
    f = open('data.pkl','rb')
    training_data = cPickle.load(f)
    f.close()
    
    
    f = open('test.pkl','rb')
    test_data = cPickle.load(f)
    f.close()
    
    return (training_data,test_data)

def load_data_wrapper():
    tr_d,te_d = load_data()
    training_inputs = [np.reshape(x,(ImageWidth*ImageHeight,1)) for x in tr_d[0]]
    training_results = [vectorized_result(y) for y in tr_d[1]]
    training_data = zip(training_inputs,training_results)
    test_inputs = [np.reshape(x,(ImageWidth*ImageHeight,1)) for x in te_d[0]]
    test_data = zip(test_inputs,te_d[1])
    return (training_data,test_data)
这段代码的作用是读取生成的pkl文件,并以标准化的格式返回。

其中vectorized_result的作用是将一个数值转化为向量,比如在手写数字问题中,一共有10个类,需要的向量长度为10,则1应该转化为[0,1,0,0,0,0,0,0,0,0],2应该转化为[0,0,1,0,0,0,0,0,0,0].

接下来便是最核心的代码:

import myalgorithm				#自己的算法
import numpy as np

import random

class Network(object):
    
    def __init__(self,sizes):						#初始化,sizes的形式一般为[784,50,10,10]之类的
        self.num_layers = len(sizes)
        self.sizes = sizes
        self.biases = [np.random.randn(y,1) for y in sizes[1:]]		#偏置初始化
        self.weights = [np.random.randn(y,x)				#权值初始化
                        for x,y in zip(sizes[:-1],sizes[1:])]
                            
    def feedforward(self,a):						#前向传播过程
        for b,w in zip(self.biases,self.weights):
            a = myalgorithm.sigmoid(np.dot(w,a)+b)
        return a
     
    def update_mini_batch(self,mini_batch,eta):				#根据一个minibatch训练样本调整参数
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        
        for x,y in mini_batch:
            delta_nabla_b,delta_nabla_w = self.backprop(x,y)
            nabla_b = [nb + dnb for nb,dnb in zip(nabla_b,delta_nabla_b)]
            nabla_w = [nw + dnw for nw,dnw in zip(nabla_w,delta_nabla_w)]
            
        self.weights = [w - (eta/len(mini_batch))*nw
                        for w,nw in zip(self.weights,nabla_w)]
        self.biases = [b - (eta/len(mini_batch))*nb
                        for b,nb in zip(self.biases,nabla_b)]
    
    def backprop(self,x,y):						#反向传播
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        
        activation = x
        activations = [x]
        zs = []
        for b,w in zip(self.biases,self.weights):
            z = np.dot(w,activation)+b
            zs.append(z)
            activation = myalgorithm.sigmoid(z)
            activations.append(activation)
            
        delta = self.cost_derivative(activations[-1],y)*myalgorithm.sigmoid_prime(zs[-1])
        nabla_b[-1] = delta
        nabla_w[-1] = np.dot(delta,activations[-2].transpose())
        for l in xrange(2,self.num_layers):
            z = zs[-l]
            sp = myalgorithm.sigmoid_prime(z)
            delta = np.dot(self.weights[-l+1].transpose(),delta) * sp
            nabla_b[-l] = delta
            nabla_w[-l] = np.dot(delta,activations[-l-1].transpose())                          
        return (nabla_b,nabla_w)

    def evaluate(self,test_data):						#测试函数
        test_results = [(np.argmax(self.feedforward(x)),y)
                        for (x,y) in test_data]
        return sum(int(x == y)for (x,y) in test_results)
        
    def cost_derivative(self,output_activations,y):				#误差函数导函数
        return (output_activations - y)
        
        
    def SGD(self,training_data,epochs,mini_batch_size,eta,test_data = None):	#SGD算法
        if test_data:
            n_test = len(test_data)
        n = len(training_data)
        for j in xrange(epochs):
            random.shuffle(training_data)
            mini_batches = [training_data[k:k+mini_batch_size] for k in xrange(0,n,mini_batch_size)]
        
            for mini_batch in mini_batches:
                self.update_mini_batch(mini_batch,eta)
            if test_data:
                print "Epoch {0}:{1}/{2}".format(j,self.evaluate(test_data),n_test)
            else:
                print "Epoch {0} complete".format(j)

代码解释见注释,

然后便可以训练:

import data
training_data,test_data = data.load_data_wrapper()

import network
net = network.Network([784,30,10])
net.SGD(training_data,30,10,1.5,test_data = test_data)

import cPickle
write_file = open('weight.pkl','wb')
cPickle.dump([net.weights[:],net.biases[:]],write_file,-1)
write_file.close()
训练完成后把权值存储起来。

如果想使用训练的模型进行分类,也很简单,如下代码:

import numpy
import commondata
from PIL import Image
import cPickle
import myalgorithm

filename = 'test1.jpg'			#需要分类的文件名

read_file = open('weight.pkl','rb')
weights,biases = cPickle.load(read_file)
read_file.close()

def outcome(weights,biases,a):
    for b,w in zip(biases,weights):
        a = myalgorithm.sigmoid(numpy.dot(w,a)+b)
    return numpy.argmax(a)

def get_predict(filename):
    image = Image.open(filename)
    image = image.convert('L')
    image = image.resize((commondata.ImageHeight,commondata.ImageWidth))
    image_narray = numpy.asarray(image,dtype = 'float64')/256
    image_vector = numpy.ndarray.flatten(image_narray)
    test = numpy.reshape(image_vector,(commondata.ImageHeight*commondata.ImageHeight,1))
    result = outcome(weights,biases,test)
    print result

 

调用get_predict函数便可以预测图片所属的类别


整个项目代码: http://download.csdn.net/detail/zsy162534/9592826



  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值