【问题标题】:Classifying handwritten digits with single layer perceptron使用单层感知器对手写数字进行分类
【发布时间】:2017-07-08 02:09:47
【问题描述】:

我想用一个简单的 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

【问题讨论】:

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


    【解决方案1】:

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

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

    您需要做的是在训练期间呈现来自所有课程的输入,例如以随机顺序。这样网络将能够找到不同类之间的边界。

    【讨论】:

    • 谢谢。你是说当我使用一堂课和训练时,我的网络会收敛,而对于第二堂课,训练根本不会发生?如果这是我的问题,那么我可以将批量学习用于许多任务(多类),对吧?
    • @Fcoder:训练仍然会进行,但网络为第一类找到的解决方案可能与适用于所有类的任何合理解决方案相去甚远,至少需要很长时间.为第一类训练的网络的输出很可能甚至不取决于输入,而仅取决于偏差值。是的,你应该从一开始就展示所有类的模式。
    【解决方案2】:

    如果您的目标是制作一个可以对某个数字进行分类的感知器,那么权重的初始化(第 3 步)应该在训练(第 8 步)之前完成,这样每次训练模型时都会初始化权重(不同的数字)。

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

    【讨论】:

      猜你喜欢
      • 2013-12-11
      • 2021-07-25
      • 2021-07-31
      • 2018-03-27
      • 2013-01-14
      • 2014-06-28
      • 2016-08-23
      • 2014-04-29
      相关资源
      最近更新 更多