【机器学习】实验四⽤python实现BP算法识别MNIST数据集⼿写数字
⽂章⽬录
⼀、初始化
self.w_ =[np.random.randn(y, x)for x, y in zip(sizes[:-1], sizes[1:])]
⾸先中括号[ ]表明w_是⼀个列表。中括号⾥⾯的代码⽤来说明这个列表中是什么内容。
1、np.random.randn(y, x)
numpy.random.randn(d0,d1,…,dn)
randn函数返回⼀个或⼀组样本,具有标准正态分布。
dn表格每个维度
返回值为指定维度的array
np.random.randn() # 当没有参数时,返回单个数据
⽰例如下:
所以上⾯代码中的randn返回y⾏,x列的正态分布矩阵。
2、zip(sizes[:-1], sizes[1:])
zip() 函数⽤于将可迭代的对象作为参数,将对象中对应的元素打包成⼀个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。
我们可以使⽤ list() 转换来输出列表。
如果各个迭代器的元素个数不⼀致,则返回列表长度与最短的对象相同,利⽤ * 号操作符,可以将元组解压为列表。
下⾯看具体的例⼦来理解zip的使⽤
上⾯的代码zip(sizes[:-1], sizes[1:])直接查看main中内容,可知,zip中第⼀个参数是[784, 40], 第⼆个参数是[40,10], 所以它的返回值是[(784, 40),(40,10)].
3、神奇的for循环
先看⼀个简单的例⼦
可以把for的这种形式想象成数学中集合的表⽰,⾸先说明这个列表中是什么东西,然后说明这些东西满⾜什么条件。
⼀个稍微复杂点的例⼦
我们在加上randn语句来看看这到底是在⼲嘛
可以看到,e⾥⾯有三个array对象,第⼀个是1⾏4列,第⼆个是2⾏5列,第三个是3⾏6列。所以这句是在说e是⼀个列表,它⾥⾯的元素是randn产⽣的array,有多少次循环就有多少个array,每次array的格式都由x,y循环变量来确定。
4、终于看懂了⼀句代码
终于我们可以看懂那句代码了self.w_ = [np.random.randn(y, x) for x, y in zip(sizes[:-1], sizes[1:])]w_⾥⾯存放的是array,按照main中的输⼊参数,W_中有两个对象,⼀个对象是784⾏40列的正态分布array,另⼀个对象是40⾏10列的array。
也就是说,第⼀个array共40列,每⼀列代表第⼆层中⼀个神经元的输⼊权重(每个神经元有784个输⼊)。
第⼆个array共10列,每⼀列代表第三层中⼀个神经元的输⼊权重(每个神经元有40个输⼊)。
总结⼀下,那句代码为权值的存放开辟了内存空间,同时初始化了权值矩阵。
5、偏移初始化
self.b_ = [np.random.randn(y, 1) for y in sizes[1:]]
看懂了上⾯的那句,这句就不是啥难题了。⾸先b_同样是⼀个列表,⾥⾯是array对象,这些array对象都只有⼀列,按照main中传进来的参数,第⼀个array有40⾏,每⾏⼀个元素,对应神经⽹络第⼆层每个神经元的偏移量。第⼆个array有10⾏,每⾏⼀个元素,对应第三层中每个神经元的偏移量。
⼆、SGD函数说明
def SGD(self, training_data, epochs, mini_batch_size, eta, test_data=None):
参数说明:
training_data是训练数据(x, y);epochs是训练次数;mini_batch_size是每次训练样本数;eta是learning rate
这个函数主体是⼀个for循环,循环变量epochs控制循环次数,循环次数也是训练⼏轮。
1、random.shuffle(training_data)
这句是打乱training_data的内部顺序,因为下⾯紧跟着就要按照mini_batch_size进⾏分批,如果不打乱,同⼀块相同形式的图⽚可能会被分到同⼀个batch,导致对训练结果产⽣负⾯影响。打乱验证:
2、mini_batches = [training_data[k:k+mini_batch_size] for k in range(0, n,
mini_batch_size)]
这句就是分批了,[ ]表⽰mini_batche是⼀个列表,⾥⾯的语句来说明它⾥⾯到底是什么东西,training_data[k:k+mini_batch_size]说明mini_batches⾥⾯的元素是training_data的⼦集,后⾯的for语句说明了k所满⾜的关系:k从0取值每隔mini_batch_size取⼀个值,直到n,这样就把⼀个⼤⼩为n的训练数据集分成了多个⼤⼩为mini_batch_size的⼦集。分包验证:
self.update_mini_batch(mini_batch, eta)for循环中这句就是真正学习的过程,没学习⼀个包更新⼀个权重和偏移。
然后后⾯的if语句如果传进来了测试数据集的话就对这⼀轮的学习结果进⾏评估,并打印出评估结果。
三、其他函数的简单说明
def sigmoid(self, z):这是sigmiod函数,激活函数,控制每个神经元的输出在0-1范围之内。
def sigmoid_prime(self, z):Sigmoid函数的导函数,⽤在反向传播误差,更新权重时。
def feedforward(self, x):前馈,根据输⼊的x,进⾏⼀次迭代,返回结果是列表,⾥⾯包含输出层神经元应该输出的结果,每层每个神经元使⽤下⾯的公式计算输出,然后再把上⼀层的输出值赋给x继续迭代。
def backprop(self, x, y):误差反向传播更新权值矩阵。x是输⼊向量,y是标签。
如果将要计算输出层的更新权重:
如果不是输出层:
def update_mini_batch(self, mini_batch, eta):更新权重.
def cost_derivative(self, output_activations, y):返回output_activations和y之差。
def load_samples(dataset="training_data"):根据参数加载数据集。并将图像和标签对应起来。
def load_mnist(dataset="training_data", digits=np.arange(10), path="."):根据参数从⽂件中读取相关数据。
def evaluate(self, test_data):根据测试数据集对模型进⾏评估,看有多少识别结果和标签⼀致。
四、实验结果
完整代码
附:MNIST数据集⽂件格式(官⽹说明翻译)
//括号中的英语是原⽂中的单词,为防⽌翻译出现歧义,特意标注
⼀些说明
⼿写数字MNIST数据库,可以从本页下载(available),它有⼀个60000个样例的训练数据集和⼀个10000个样例的测试数据集。它是⼀个⼤数据集的⼦集(可以从NIST下载)。⾥⾯的数字已经被尺⼨归⼀化并且集中在固定⼤⼩的图像中。
它是⼀个很好的数据集,对想要学习技术或者现实世界数据的模式识别⽅法⽽花很少的时间在预处理和格式化上的⼈来说。
四个⽂件在下⾯这些站点可下载:
training set images (9912422 bytes)
training set labels (28881 bytes)
test set images (1648877 bytes)
test set labels (4542 bytes)
请注意你的浏览器可能在没有通知你的情况下对⽂件进⾏解压。 如果你下载的⽂件⼤⼩超过上⾯说明的⼤⼩,他们有可能是被你的浏览器解压了。简单的对它们重新命名去除掉.gz扩展即可。有些⼈问我“我的程序⽆法打开你的图像⽂件”。这些⽂件并不是任何标准的图像格式。你必须写你⾃⼰的程序(⾮常简单)去读取他们。⽂件格式在本页的下⾯进⾏了描述。
NIST对原始的⿊⽩(双⽔平)图像进⾏了尺⼨标准化,以适合于20x20像素的盒⼦(box),同时保留了它们的⾼宽⽐。由于归⼀化算法使⽤了抗混叠技术,所以结果图⽚包含灰度级。通过计算像素的质⼼,将图像中⼼化到⼀个28x28的图像中,然后平移图像,使这个点位于28x28区域的中⼼。
random python
MNIST数据集⽂件格式
数据存储在⼀个⾮常简单的⽂件格式中,这种格式⽤来存储向量和多维矩阵。这种格式的⼀般信息在本页的末尾给出,但是你不需要为了使⽤⽂件⽽去读那些东西。
所有在⽂件中的整数都⽤⼤多数⾮intel处理器使⽤的MSB优先(high endian)格式存储。intel处理器的使⽤者和其他low-endian机器必须翻转头部字节.
有四个⽂件
train-images-idx3-ubyte: training set images
train-labels-idx1-ubyte: training set labels
t10k-images-idx3-ubyte:  test set images
t10k-labels-idx1-ubyte:  test set labels
训练数据集包含60000个样例,测试数据集包含10000个样例。
测试数据集的前5000个样例取⾃原始NIST训练集。后5000个取⾃原始NIST测试集。前5000个⽐后5000个更加清晰容易。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。