用python实现手写数字识别

2019-02-14  本文已影响61人  此间不留白

前言

在之前的学习中,已经对神经网络的算法具体进行了学习和了解。现在,我们可以用python通过两种方法来实现手写数字的识别。这两种方法分别是多元逻辑回归和神经网络方法。

用多元逻辑回归手写数字识别

import matplotlib.pyplot as plt
import numpy as np
import scipy.io as scio
input_layer_size = 400  # 20x20 像素矩阵
num_labels = 10     # 手写数字 0,1,2,3,4,5,6,7,8,9

最后,绘图实现效果如下


def lr_cost_function(theta, X, y, lmd):
    m = y.size
    cost = 0
    grad = np.zeros(theta.shape)
    reg_theta = theta[1:]
    hy = sigmoid(np.dot(X,theta))
    cost = np.sum(-y * np.log(hy) - np.subtract(1, y) * np.log(np.subtract(1, hy))) / m + (lmd / (2 * m)) * np.sum(reg_theta * reg_theta)
    
    grad = np.dot(X.T,  np.subtract(hy, y)) / m
    grad[1:] = grad[1:] + reg_theta * (lmd / m) #正则化
    return cost, grad
def sigmoid(z):
    return 1/(1+np.exp(-z))

人为构造一些参数值,计算结果如下所示:

theta_t = np.array([-2, -1, 1, 2])
X_t = np.c_[np.ones(5), np.arange(1, 16).reshape((3, 5)).T/10]
y_t = np.array([1, 0, 1, 0, 1])
lmda_t = 3
cost, grad = lr_cost_function(theta_t, X_t, y_t, lmda_t)
print(cost,grad)
def one_vs_all(X, y, num_labels, lmd):
    
    (m, n) = X.shape
    all_theta = np.zeros((num_labels, n + 1))
    X = np.c_[np.ones(m), X]

    for i in range(num_labels):
        initial_theta = np.zeros((n + 1, 1))
        iclass = i if i else 10
        y_i = np.array([1 if x == iclass else 0 for x in y])
        print('Optimizing for handwritten number {}...'.format(i))

        def cost_func(t):
            return lr_cost_function(t, X, y_i, lmd)[0]

        def grad_func(t):
            return lr_cost_function(t, X, y_i, lmd)[1]

        theta, *unused = opt.fmin_cg(cost_func, fprime=grad_func, x0=initial_theta, maxiter=100, disp=False, 
                                     full_output=True)
        print('Done')
        all_theta[i] = theta

    return all_theta

调用one_vs_all()函数,可以看到通过梯度下降算法得到的
\theta参数矩阵如下所示,

def predict_one_vs_all(all_theta, X):
    m = X.shape[0]
    num_labels = all_theta.shape[0]
    p = np.zeros(m)
    X = np.c_[np.ones(m), X]
    result = np.dot(all_theta, X.T)
    result = np.roll(result, -1, axis=0)
    result = np.vstack([np.zeros(m), result])
    p = np.argmax(result, axis=0)
    return p
pred = predict_one_vs_all(all_theta, X)
print('Training set accuracy: {}'.format(np.mean(pred == y)*100))

经过计算,识别精确率如下所示:


用神经网路实现手写数字识别



data = scio.loadmat('ex3weights.mat')  #加载权重矩阵
theta1 = data['Theta1']
theta2 = data['Theta2']
def predict(theta1, theta2, x):
    num_labels = theta2.shape[0]
    p = np.zeros(m)
    x = np.c_[np.ones(m), x]
    h1 = sigmoid(np.dot(x, theta1.T))
    h1 = np.c_[np.ones(h1.shape[0]), h1]
    h2 = sigmoid(np.dot(h1, theta2.T))
    p = np.argmax(h2, axis=1) + 1

    return p

分析以上代码,我们可以发现这是有一个输入层(X矩阵),一个
隐藏层(由X矩阵计算得到的h1),由隐藏层计算得到的输出层(h2),最后,由输出层得到分类结果。
通过神经网络得到识别的精确率如下所示:

上一篇 下一篇

猜你喜欢

热点阅读