学习人工智能时,我给自己定了一个目标--用Python写一个简单的神经网络。为了确保真得理解它,我要求自己不使用任何神经网络库,从头写起。多亏了Andrew Trask写得一篇精彩的博客,我做到了!下面贴出那九行代码:
在这篇文章中,我将解释我是如何做得,以便你可以写出你自己的。我将会提供一个长点的但是更完美的源代码。
首先,神经网络是什么?人脑由几千亿由突触相互连接的细胞(神经元)组成。突触传入足够的兴奋就会引起神经元的兴奋。这个过程被称为“思考”。
我们可以在计算机上写一个神经网络来模拟这个过程。不需要在生物分子水平模拟人脑,只需模拟更高层级的规则。我们使用矩阵(二维数据表格)这一数学工具,并且为了简单明了,只模拟一个有3个输入和一个输出的神经元。
我们将训练神经元解决下面的问题。前四个例子被称作训练集。你发现规律了吗?‘?’是0还是1?
你可能发现了,输出总是等于输入中最左列的值。所以‘?’应该是1。
训练过程
但是如何使我们的神经元回答正确呢?赋予每个输入一个权重,可以是一个正的或负的数字。拥有较大正(或负)权重的输入将决定神经元的输出。首先设置每个权重的初始值为一个随机数字,然后开始训练过程:
取一个训练样本的输入,使用权重调整它们,通过一个特殊的公式计算神经元的输出。
计算误差,即神经元的输出与训练样本中的期待输出之间的差值。
根据误差略微地调整权重。
重复这个过程1万次。
最终权重将会变为符合训练集的一个最优解。如果使用神经元考虑这种规律的一个新情形,它将会给出一个很棒的预测。
这个过程就是back propagation。
计算神经元输出的公式
你可能会想,计算神经元输出的公式是什么?首先,计算神经元输入的加权和,即
接着使之规范化,结果在0,1之间。为此使用一个数学函数--Sigmoid函数:
Sigmoid函数的图形是一条“S”状的曲线。
把第一个方程代入第二个,计算神经元输出的最终公式为:
你可能注意到了,为了简单,我们没有引入最低兴奋阈值。
调整权重的公式
我们在训练时不断调整权重。但是怎么调整呢?可以使用“Error Weighted Derivative”公式:
为什么使用这个公式?首先,我们想使调整和误差的大小成比例。其次,乘以输入(0或1),如果输入是0,权重就不会调整。最后,乘以Sigmoid曲线的斜率(图4)。为了理解最后一条,考虑这些:
我们使用Sigmoid曲线计算神经元的输出
如果输出是一个大的正(或负)数,这意味着神经元采用这种(或另一种)方式
从图四可以看出,在较大数值处,Sigmoid曲线斜率小
如果神经元认为当前权重是正确的,就不会对它进行很大调整。乘以Sigmoid曲线斜率便可以实现这一点
Sigmoid曲线的斜率可以通过求导得到:
把第二个等式代入第一个等式里,得到调整权重的最终公式:
当然有其他公式,它们可以使神经元学习得更快,但是这个公式的优点是非常简单。
构造Python代码
虽然我们没有使用神经网络库,但是将导入Python数学库numpy里的4个方法。分别是:
exp--自然指数
array--创建矩阵
dot--进行矩阵乘法
random--产生随机数
比如, 我们可以使用array()方法表示前面展示的训练集:
“.T”方法用于矩阵转置(行变列)。所以,计算机这样存储数字:
我觉得我们可以开始构建更优美的源代码了。给出这个源代码后,我会做一个总结。
我对每一行源代码都添加了注释来解释所有内容。注意在每次迭代时,我们同时处理所有训练集数据。所以变量都是矩阵(二维数据表格)。下面是一个用Python写地完整的示例代码。
我们做到了!我们用Python构建了一个简单的神经网络!
首先神经网络对自己赋予随机权重,然后使用训练集训练自己。接着,它考虑一种新的情形[1, 0, 0]并且预测了0.99993704。正确答案是1。非常接近!
传统计算机程序通常不会学习。而神经网络却能自己学习,适应并对新情形做出反应,这是多么神奇,就像人类一样。
谷歌人工智能写作项目:小发猫
上周末利用python简单实现了一个卷积神经网络,只包含一个卷积层和一个maxpooling层,pooling层后面的多层神经网络采用了softmax形式的输出自己动手编写python神经网络。实验输入仍然采用MNIST图像使用10个feature map时,卷积和pooling的结果分别如下所示。
部分源码如下:
[python] view plain copy
#coding=utf-8
'''''
Created on 2014年11月30日
@author: Wangliaofan
'''
import numpy
import struct
import matplotlib.pyplot as plt
import math
import random
import copy
#test
from BasicMultilayerNeuralNetwork import BMNN2
def sigmoid(inX):
if 1.0+numpy.exp(-inX)== 0.0:
return 999999999.999999999
return 1.0/(1.0+numpy.exp(-inX))
def difsigmoid(inX):
return sigmoid(inX)*(1.0-sigmoid(inX))
def tangenth(inX):
return (1.0*math.exp(inX)-1.0*math.exp(-inX))/(1.0*math.exp(inX)+1.0*math.exp(-inX))
def cnn_conv(in_image, filter_map,B,type_func='sigmoid'):
#in_image[num,feature map,row,col]=>in_image[Irow,Icol]
#features map[k filter,row,col]
#type_func['sigmoid','tangenth']
#out_feature[k filter,Irow-row+1,Icol-col+1]
shape_image=numpy.shape(in_image)#[row,col]
#print "shape_image",shape_image
shape_filter=numpy.shape(filter_map)#[k filter,row,col]
if shape_filter[1]>shape_image[0] or shape_filter[2]>shape_image[1]:
raise Exception
shape_out=(shape_filter[0],shape_image[0]-shape_filter[1]+1,shape_image[1]-shape_filter[2]+1)
out_feature=numpy.zeros(shape_out)
k,m,n=numpy.shape(out_feature)
for k_idx in range(0,k):
#rotate 180 to calculate conv
c_filter=numpy.rot90(filter_map[k_idx,:,:], 2)
for r_idx in range(0,m):
for c_idx in range(0,n):
#conv_temp=numpy.zeros((shape_filter[1],shape_filter[2]))
conv_temp=numpy.dot(in_image[r_idx:r_idx+shape_filter[1],c_idx:c_idx+shape_filter[2]],c_filter)
sum_temp=numpy.sum(conv_temp)
if type_func=='sigmoid':
out_feature[k_idx,r_idx,c_idx]=sigmoid(sum_temp+B[k_idx])
elif type_func=='tangenth':
out_feature[k_idx,r_idx,c_idx]=tangenth(sum_temp+B[k_idx])
else:
raise Exception
return out_feature
def cnn_maxpooling(out_feature,pooling_size=2,type_pooling="max"):
k,row,col=numpy.shape(out_feature)
max_index_Matirx=numpy.zeros((k,row,col))
out_row=int(numpy.floor(row/pooling_size))
out_col=int(numpy.floor(col/pooling_size))
out_pooling=numpy.zeros((k,out_row,out_col))
for k_idx in range(0,k):
for r_idx in range(0,out_row):
for c_idx in range(0,out_col):
temp_matrix=out_feature[k_idx,pooling_size*r_idx:pooling_size*r_idx+pooling_size,pooling_size*c_idx:pooling_size*c_idx+pooling_size]
out_pooling[k_idx,r_idx,c_idx]=numpy.amax(temp_matrix)
max_index=numpy.argmax(temp_matrix)
#print max_index
#print max_index/pooling_size,max_index%pooling_size
max_index_Matirx[k_idx,pooling_size*r_idx+max_index/pooling_size,pooling_size*c_idx+max_index%pooling_size]=1
return out_pooling,max_index_Matirx
def poolwithfunc(in_pooling,W,B,type_func='sigmoid'):
k,row,col=numpy.shape(in_pooling)
out_pooling=numpy.zeros((k,row,col))
for k_idx in range(0,k):
for r_idx in range(0,row):
for c_idx in range(0,col):
out_pooling[k_idx,r_idx,c_idx]=sigmoid(W[k_idx]*in_pooling[k_idx,r_idx,c_idx]+B[k_idx])
return out_pooling
#out_feature is the out put of conv
def backErrorfromPoolToConv(theta,max_index_Matirx,out_feature,pooling_size=2):
k1,row,col=numpy.shape(out_feature)
error_conv=numpy.zeros((k1,row,col))
k2,theta_row,theta_col=numpy.shape(theta)
if k1!=k2:
raise Exception
for idx_k in range(0,k1):
for idx_row in range( 0, row):
for idx_col in range( 0, col):
error_conv[idx_k,idx_row,idx_col]=\
max_index_Matirx[idx_k,idx_row,idx_col]*\
float(theta[idx_k,idx_row/pooling_size,idx_col/pooling_size])*\
difsigmoid(out_feature[idx_k,idx_row,idx_col])
return error_conv
def backErrorfromConvToInput(theta,inputImage):
k1,row,col=numpy.shape(theta)
#print "theta",k1,row,col
i_row,i_col=numpy.shape(inputImage)
if row>i_row or col> i_col:
raise Exception
filter_row=i_row-row+1
filter_col=i_col-col+1
detaW=numpy.zeros((k1,filter_row,filter_col))
#the same with conv valid in matlab
for k_idx in range(0,k1):
for idx_row in range(0,filter_row):
for idx_col in range(0,filter_col):
subInputMatrix=inputImage[idx_row:idx_row+row,idx_col:idx_col+col]
#print "subInputMatrix",numpy.shape(subInputMatrix)
#rotate theta 180
#print numpy.shape(theta)
theta_rotate=numpy.rot90(theta[k_idx,:,:], 2)
#print "theta_rotate",theta_rotate
dotMatrix=numpy.dot(subInputMatrix,theta_rotate)
detaW[k_idx,idx_row,idx_col]=numpy.sum(dotMatrix)
detaB=numpy.zeros((k1,1))
for k_idx in range(0,k1):
detaB[k_idx]=numpy.sum(theta[k_idx,:,:])
return detaW,detaB
def loadMNISTimage(absFilePathandName,datanum=60000):
images=open(absFilePathandName,'rb')
buf=images.read()
index=0
magic, numImages , numRows , numColumns = struct.unpack_from('>IIII' , buf , index)
print magic, numImages , numRows , numColumns
index += struct.calcsize('>IIII')
if magic != 2051:
raise Exception
datasize=int(784*datanum)
datablock=">"+str(datasize)+"B"
#nextmatrix=struct.unpack_from('>47040000B' ,buf, index)
nextmatrix=struct.unpack_from(datablock ,buf, index)
nextmatrix=numpy.array(nextmatrix)/255.0
#nextmatrix=nextmatrix.reshape(numImages,numRows,numColumns)
#nextmatrix=nextmatrix.reshape(datanum,1,numRows*numColumns)
nextmatrix=nextmatrix.reshape(datanum,1,numRows,numColumns)
return nextmatrix, numImages
def loadMNISTlabels(absFilePathandName,datanum=60000):
labels=open(absFilePathandName,'rb')
buf=labels.read()
index=0
magic, numLabels = struct.unpack_from('>II' , buf , index)
print magic, numLabels
index += struct.calcsize('>II')
if magic != 2049:
raise Exception
datablock=">"+str(datanum)+"B"
#nextmatrix=struct.unpack_from('>60000B' ,buf, index)
nextmatrix=struct.unpack_from(datablock ,buf, index)
nextmatrix=numpy.array(nextmatrix)
return nextmatrix, numLabels
def simpleCNN(numofFilter,filter_size,pooling_size=2,maxIter=1000,imageNum=500):
decayRate=0.01
MNISTimage,num1=loadMNISTimage("F:\Machine Learning\UFLDL\data\common\\train-images-idx3-ubyte",imageNum)
print num1
row,col=numpy.shape(MNISTimage[0,0,:,:])
out_Di=numofFilter*((row-filter_size+1)/pooling_size)*((col-filter_size+1)/pooling_size)
MLP=BMNN2.MuiltilayerANN(1,[128],out_Di,10,maxIter)
MLP.setTrainDataNum(imageNum)
MLP.loadtrainlabel("F:\Machine Learning\UFLDL\data\common\\train-labels-idx1-ubyte")
MLP.initialweights()
#MLP.printWeightMatrix()
rng = numpy.random.RandomState(23455)
W_shp = (numofFilter, filter_size, filter_size)
W_bound = numpy.sqrt(numofFilter * filter_size * filter_size)
W_k=rng.uniform(low=-1.0 / W_bound,high=1.0 / W_bound,size=W_shp)
B_shp = (numofFilter,)
B= numpy.asarray(rng.uniform(low=-.5, high=.5, size=B_shp))
cIter=0
while cIter
cIter += 1
ImageNum=random.randint(0,imageNum-1)
conv_out_map=cnn_conv(MNISTimage[ImageNum,0,:,:], W_k, B,"sigmoid")
out_pooling,max_index_Matrix=cnn_maxpooling(conv_out_map,2,"max")
pool_shape = numpy.shape(out_pooling)
MLP_input=out_pooling.reshape(1,1,out_Di)
#print numpy.shape(MLP_input)
DetaW,DetaB,temperror=MLP.backwardPropogation(MLP_input,ImageNum)
if cIter%50 ==0 :
print cIter,"Temp error: ",temperror
#print numpy.shape(MLP.Theta[MLP.Nl-2])
#print numpy.shape(MLP.Ztemp[0])
#print numpy.shape(MLP.weightMatrix[0])
theta_pool=MLP.Theta[MLP.Nl-2]*MLP.weightMatrix[0].transpose()
#print numpy.shape(theta_pool)
#print "theta_pool",theta_pool
temp=numpy.zeros((1,1,out_Di))
temp[0,:,:]=theta_pool
back_theta_pool=temp.reshape(pool_shape)
#print "back_theta_pool",numpy.shape(back_theta_pool)
#print "back_theta_pool",back_theta_pool
error_conv=backErrorfromPoolToConv(back_theta_pool,max_index_Matrix,conv_out_map,2)
#print "error_conv",numpy.shape(error_conv)
#print error_conv
conv_DetaW,conv_DetaB=backErrorfromConvToInput(error_conv,MNISTimage[ImageNum,0,:,:])
#print "W_k",W_k
#print "conv_DetaW",conv_DetaW
用keras框架较为方便
首先安装anaconda,然后通过pip安装keras
以下转自wphh的博客。
#coding:utf-8 ''' GPU run command: THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python cnn.py CPU run command: python cnn.py 2016.06.06更新: 这份代码是keras开发初期写的,当时keras还没有现在这么流行,文档也还没那么丰富,所以我当时写了一些简单的教程。 现在keras的API也发生了一些的变化,建议及推荐直接上keras.io看更加详细的教程。 ''' #导入各种用到的模块组件 from __future__ import absolute_import from __future__ import print_function from keras.preprocessing.image import ImageDataGenerator from keras.models import Sequential from keras.layers.core import Dense, Dropout, Activation, Flatten from keras.layers.advanced_activations import PReLU from keras.layers.convolutional import Convolution2D, MaxPooling2D from keras.optimizers import SGD, Adadelta, Adagrad from keras.utils import np_utils, generic_utils from six.moves import range from data import load_data import random import numpy as np np.random.seed(1024) # for reproducibility #加载数据 data, label = load_data() #打乱数据 index = [i for i in range(len(data))] random.shuffle(index) data = data[index] label = label[index] print(data.shape[0], ' samples') #label为0~9共10个类别,keras要求格式为binary class matrices,转化一下,直接调用keras提供的这个函数 label = np_utils.to_categorical(label, 10) ############### #开始建立CNN模型 ############### #生成一个model model = Sequential() #第一个卷积层,4个卷积核,每个卷积核大小5*5。1表示输入的图片的通道,灰度图为1通道。 #border_mode可以是valid或者full,具体看这里说明: #激活函数用tanh #你还可以在model.add(Activation('tanh'))后加上dropout的技巧: model.add(Dropout(0.5)) model.add(Convolution2D(4, 5, 5, border_mode='valid',input_shape=(1,28,28))) model.add(Activation('tanh')) #第二个卷积层,8个卷积核,每个卷积核大小3*3。4表示输入的特征图个数,等于上一层的卷积核个数 #激活函数用tanh #采用maxpooling,poolsize为(2,2) model.add(Convolution2D(8, 3, 3, border_mode='valid')) model.add(Activation('tanh')) model.add(MaxPooling2D(pool_size=(2, 2))) #第三个卷积层,16个卷积核,每个卷积核大小3*3 #激活函数用tanh #采用maxpooling,poolsize为(2,2) model.add(Convolution2D(16, 3, 3, border_mode='valid')) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) #全连接层,先将前一层输出的二维特征图flatten为一维的。 #Dense就是隐藏层。16就是上一层输出的特征图个数。4是根据每个卷积层计算出来的:(28-5+1)得到24,(24-3+1)/2得到11,(11-3+1)/2得到4 #全连接有128个神经元节点,初始化方式为normal model.add(Flatten()) model.add(Dense(128, init='normal')) model.add(Activation('tanh')) #Softmax分类,输出是10类别 model.add(Dense(10, init='normal')) model.add(Activation('softmax')) ############# #开始训练模型 ############## #使用SGD + momentum #model.compile里的参数loss就是损失函数(目标函数) sgd = SGD(lr=0.05, decay=1e-6, momentum=0.9, nesterov=True) model.compile(loss='categorical_crossentropy', optimizer=sgd,metrics=["accuracy"]) #调用fit方法,就是一个训练过程. 训练的epoch数设为10,batch_size为100. #数据经过随机打乱shuffle=True。verbose=1,训练过程中输出的信息,0、1、2三种方式都可以,无关紧要。show_accuracy=True,训练时每一个epoch都输出accuracy。 #validation_split=0.2,将20%的数据作为验证集。 model.fit(data, label, batch_size=100, nb_epoch=10,shuffle=True,verbose=1,validation_split=0.2) """ #使用data augmentation的方法 #一些参数和调用的方法,请看文档 datagen = ImageDataGenerator( featurewise_center=True, # set input mean to 0 over the dataset samplewise_center=False, # set each sample mean to 0 featurewise_std_normalization=True, # divide inputs by std of the dataset samplewise_std_normalization=False, # divide each input by its std zca_whitening=False, # apply ZCA whitening rotation_range=20, # randomly rotate images in the range (degrees, 0 to 180) width_shift_range=0.2, # randomly shift images horizontally (fraction of total width) height_shift_range=0.2, # randomly shift images vertically (fraction of total height) horizontal_flip=True, # randomly flip images vertical_flip=False) # randomly flip images # compute quantities required for featurewise normalization # (std, mean, and principal components if ZCA whitening is applied) datagen.fit(data) for e in range(nb_epoch): print('-'*40) print('Epoch', e) print('-'*40) print("Training...") # batch train with realtime data augmentation progbar = generic_utils.Progbar(data.shape[0]) for X_batch, Y_batch in datagen.flow(data, label): loss,accuracy = model.train(X_batch, Y_batch,accuracy=True) progbar.add(X_batch.shape[0], values=[("train loss", loss),("accuracy:", accuracy)] ) """
学习人工智能时,我给自己定了一个目标--用Python写一个简单的神经网络。为了确保真得理解它,我要求自己不使用任何神经网络库,从头写起。多亏了Andrew Trask写得一篇精彩的博客,我做到了!下面贴出那九行代码
python是一款应用非常广泛的脚本程序语言,谷歌公司的网页就是用python编写。python在生物信息、统计、网页制作、计算等多个领域都体现出了强大的功能。python和其他脚本语言如java、R、Perl 一样,都可以直接在命令行里运行脚本程序。工具/原料
python;CMD命令行;windows操作系统
方法/步骤
1、首先下载安装python,建议安装2.7版本以上,3.0版本以下,由于3.0版本以上不向下兼容,体验较差。
2、打开文本编辑器,推荐editplus,notepad等,将文件保存成 .py格式,editplus和notepad支持识别python语法。
脚本第一行一定要写上 #!usr/bin/python
表示该脚本文件是可执行python脚本
如果python目录不在usr/bin目录下,则替换成当前python执行程序的目录。
3、编写完脚本之后注意调试、可以直接用editplus调试。调试方法可自行百度。脚本写完之后,打开CMD命令行,前提是python 已经被加入到环境变量中,如果没有加入到环境变量,请百度
4、在CMD命令行中,输入 “python” + “空格”,即 ”python “;将已经写好的脚本文件拖拽到当前光标位置,然后敲回车运行即可。
官方不支持,建议等支持吧。 dll有自己版本对应的,必须使用专门为python3.4编译的dll(cv2.pyd),你拿python2.7的肯定用不了。 如果非要使用—— 方法一:自己编译opencv的源码 方法二:安装python2.7