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

时间:2017-02-18 14:57:36

标签: python machine-learning neural-network computer-vision artificial-intelligence

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

我的问题是,例如,如果我训练数字“1”然后训练其他数字,网络总是显示“1”的结果。实际上,训练发生在第一位数。我不知道是什么问题。

我认为这与批量培训有关,经过一次培训后,第二位数不能因为网络融合。但我不知道如何解决它。

我用多层感知器进行了测试,我得到了同样的行为。

注意:每当我选择一个数字并加载大量数字并开始训练时,对于其他数字,我会重新启动除重量矩阵(w0)之外的所有数据

这是我的代码:

1个导入库:

import os, struct
from array import array as pyarray
from numpy import append, array, int8, uint8, zeros
import numpy as np
from IPython.display import Image
import matplotlib.pyplot as plt
from IPython import display
from scipy.special import expit
from scipy.misc import imresize
from IPython.core.page import page
from IPython.core.formatters import format_display_data

np.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 = 4
digits=[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

2 个答案:

答案 0 :(得分:2)

使用单个类(数字)的数据训练网络直到它收敛,然后添加另一个类等等是没有意义的。

如果您只训练一个班级,所需的输出将始终相同,网络可能会快速收敛。它可能会为所有类型的输入模式生成此输出,而不仅仅是您用于训练的输出模式。

您需要做的是在训练期间提供所有课程的输入,例如以随机顺序。这样,网络就能够找到不同类之间的界限。

答案 1 :(得分:0)

如果您的目标是制作可以对特定数字进行分类的感知器,则权重的初始化(步骤3)应在训练(步骤8)之前进行,以便每次训练模型时都对权重进行初始化(不同的数字)。

总而言之,我将#3移到#8之前。

相关问题