0

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

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

我在想这与批次训练有关,一次训练后第二位数不能因为网络收敛。但我不能如何解决它。

我使用多层感知器进行测试,并得到相同的行为。

注:

1:我每次选择一个数字并加载了很多人,并开始培训,并为其他数字我重新启动的每一件事情,除了权重矩阵(W0)

这是我的代码的时间-importing库:

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

谢谢。你是说当我使用班级和火车时,我的网络会收敛,而对于第二类,训练不会发生?如果这是我的问题,那么我可以使用批量学习的许多任务(多类),对不对? – Fcoder

+1

@Fcoder:培训仍将发生,但网络为第一类人员找到的解决方案可能会远离任何适用于所有类别的明智解决方案,至少需要很长时间。为第一类训练的网络输出可能不会取决于输入,而只取决于偏差值。是的,你应该从一开始就展示来自所有课堂的模式。 –