使用单层感知器分类手写数字

我想用简单的Python代码来分类手写数字(MNIST)。我的方法是使用一个简单的单层感知器,并且采用批处理方法进行训练。

我的问题是,例如,如果我先训练数字“1”,然后再训练其他数字,网络总是显示“1”的结果。实际上,训练只发生在第一个数字上。我不知道问题出在哪里。

我认为这可能与批处理训练有关,因为在一次训练后,第二个数字无法训练,因为网络已经收敛了。但我不知道如何解决这个问题。

我还测试了多层感知器,结果表现相同。

注意:每次我选择一个数字,加载大量该数字的样本并开始训练,对于其他数字,我会重新开始所有操作,除了权重矩阵(w0)之外。

这是我的代码:

1-导入库:

import os, structfrom array import array as pyarrayfrom numpy import append, array, int8, uint8, zerosimport numpy as npfrom IPython.display import Imageimport matplotlib.pyplot as pltfrom IPython import displayfrom scipy.special import expitfrom scipy.misc import imresizefrom IPython.core.page import pagefrom IPython.core.formatters import format_display_datanp.set_printoptions(threshold=np.nan)np.set_printoptions(suppress=True)

2- Sigmoid函数:

def sigmoid(x, deriv=False):    if(deriv==True):        return x*(1-x)    return expit(x)

3- 初始化权重

np.random.seed(1)w0 = 2*np.random.random((784,10))-1

4- 读取MNIST数据集

dataset="training"path="."if dataset == "training":    fname_img = os.path.join(path, 'train-images-idx3-ubyte')    fname_lbl = os.path.join(path, 'train-labels-idx1-ubyte')elif dataset == "testing":    fname_img = os.path.join(path, 't10k-images-idx3-ubyte')    fname_lbl = os.path.join(path, 't10k-labels-idx1-ubyte')else:    raise ValueError("dataset must be 'testing' or 'training'")flbl = open(fname_lbl, 'rb')magic_nr, size = struct.unpack(">II", flbl.read(8))lbl = pyarray("b", flbl.read())flbl.close()fimg = open(fname_img, 'rb')magic_nr, size, rows, cols = struct.unpack(">IIII", fimg.read(16))img = pyarray("B", fimg.read())fimg.close()

5- 选择一个数字

number = 4digits=[number]ind = [ k for k in range(size) if lbl[k] in digits ]N = len(ind)images = zeros((N, rows, cols), dtype=uint8)labels = zeros((N, 1), dtype=int8)for i in range(len(ind)):    images[i] = array(img[ ind[i]*rows*cols : (ind[i]+1)*rows*cols ]).reshape((rows, cols))    labels[i] = lbl[ind[i]]

6- 将每个数字转换为向量,并将矩阵单元格转换为二进制:

p = np.reshape(images,(len(images),784))p[p > 0] = 1

7- 目标矩阵(每列对应一个数字)

t = np.zeros((len(images), 10),dtype=float)t[:,number] = 1

8- 训练(梯度下降)

for iter in xrange(600):    predict = sigmoid(np.dot(p,w0))    e0 = predict - t    delta0 = e0 * sigmoid(predict,True)    w0 -= 0.01*np.dot(p.T,delta0)

9- 测试

test_predict = sigmoid(np.dot(p[102],w0))print test_predict

回答:

用单一类别(数字)的数据训练网络直到收敛,然后再添加另一个类别,这样做是没有意义的。

如果你只用一个类别进行训练,所需的输出总是相同的,网络可能会很快收敛。它可能会对所有类型的输入模式产生这种输出,而不仅仅是用于训练的那些模式。

你需要做的是在训练过程中呈现所有类别的输入,例如以随机顺序。这样,网络就能找到不同类别之间的边界。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注