python_多元分类_手写字母识别

参考:原文:https://blog.csdn.net/Cowry5/article/details/80367832 

1.使用逻辑回归梯度下降方法分析(方便理解,算法没调试好,准确率不高)

代码

from scipy.io import loadmat
import numpy as np
import matplotlib.pyplot as plt
def load_data(path):#导入数据
    data=loadmat(path)
    x=data['X']
    y=data['y']
    return x,y
'''def plot_an_image(X):
    pick_one=np.random.choice(np.arange(X.shape[0]),100)
    image=X[pick_one,:]
    fig, ax=plt.subplots(nrows=10,ncols=10,sharey=True,sharex=True,figsize=(8,8))
    for row in range(10):
        for colum in range(10):
            ax[row,colum].matshow(image[10*row+colum].reshape((20,20)),cmap='gray_r')
    plt.xticks([])
    plt.yticks([])
    plt.show()'''
def plot_an_image(X):
    """
    随机打印一个数字
    """
    pick_one = np.random.randint(0, 5000)
    image = X[pick_one, :]
    fig, ax = plt.subplots(figsize=(1, 1))
    ax.matshow(image.reshape((20, 20)), cmap='gray_r')
    plt.xticks([])  # 去除刻度,美观
    plt.yticks([])
    plt.show()
    return pick_one
def sigmoid(z):
    return 1 / (1 + np.exp(-z))
def predict(X,all_theta):
    X=X.T
    h=sigmoid(all_theta@X)
    return h
def tiduxiajiang_sigmoid(x,y):
    alpha=0.0001
    maxcycle=50
    weights=np.ones(X.shape[1])
    weights=np.mat(weights)
    weights=weights.T
    x=np.mat(x)#转成矩阵
    y=np.mat(y)
    y=y.T
    x2=x.T#矩阵转逆
    for i in range(maxcycle):
        h = sigmoid(x* weights)
        error=y-h
        weights=weights+alpha*x2*error
        #print(sum(error))
        if(abs(sum(error))<=10):
            break
    return weights.T
X,y=load_data('ex3data1.mat')
X=np.insert(X,0,1,axis=1)
all_theta=np.zeros((10,X.shape[1]))
for i in range(1,11):#遍历1到10个分类
     y_i = np.array([1 if label == i else 0 for label in y])#归类,是就是1不然就归0
     all_theta[i-1:]=tiduxiajiang_sigmoid(X,y_i)#梯度下降求theta
for j in range(10):
    pick_one= np.random.randint(0, 5000)#随机生成一个整数在0到5000之间
    image = X[pick_one, :]
    data=predict(image,all_theta)
    data=list(data)
    max=0
    for i in range(1,len(data)):#将预测值转数字
        if(data[max]<data[i]):
            max=i
    print(y[pick_one, :],end=" ")#输出原本值
    print(max+1)#输出预测值

输出

[2] 2
[1] 8
[4] 4
[8] 8
[9] 8
[7] 7
[5] 8
[1] 8
[4] 4
[1] 8

2.根据上面原文进行一点点修改,准确率较高(主要是minimize的应用)

代码

from scipy.io import loadmat
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize
def load_data(path):#导入数据
    data=loadmat(path)
    x=data['X']
    y=data['y']
    return x,y
def plot_an_image(X):
    """
    随机打印一个数字
    """
    pick_one = np.random.randint(0, 5000)
    '''image = X[pick_one, :]
    fig, ax = plt.subplots(figsize=(1, 1))
    ax.matshow(image.reshape((20, 20)), cmap='gray_r')
    plt.xticks([])  # 去除刻度,美观
    plt.yticks([])
    plt.show()'''
    return pick_one
def sigmoid(z):
    return 1 / (1 + np.exp(-z))
def predict(X,all_theta):#预测函数
    X=X.T
    h=sigmoid(all_theta@X)
    return h
def regularized_cost(theta, X, y, l):
    thetaReg = theta[1:]
    first = (-y*np.log(sigmoid(X@theta))) + (y-1)*np.log(1-sigmoid(X@theta))
    reg = (thetaReg@thetaReg)*l / (2*len(X))
    return np.mean(first) + reg
def regularized_gradient(theta, X, y, l):
    thetaReg = theta[1:]
    first = (1 / len(X)) * X.T @ (sigmoid(X @ theta) - y)
    # 这里人为插入一维0,使得对theta_0不惩罚,方便计算
    reg = np.concatenate([np.array([0]), (l / len(X)) * thetaReg])
    return first + reg
def one_vs_all(X, y, l, K):
    all_theta = np.zeros((K, X.shape[1]))  # (10, 401)
    
    for i in range(1, K+1):
        theta = np.zeros(X.shape[1])
        y_i = np.array([1 if label == i else 0 for label in y])
    
        ret = minimize(fun=regularized_cost, x0=theta, args=(X, y_i, l), method='TNC',
                        jac=regularized_gradient, options={'disp': True})
        all_theta[i-1,:] = ret.x                  
    return all_theta
raw_X, raw_y = load_data('ex3data1.mat')
x=raw_X
X = np.insert(raw_X, 0, 1, axis=1) # (5000, 401)
y2=raw_y
y = raw_y.flatten()  # 这里消除了一个维度,方便后面的计算 or .reshape(-1) (5000,)
all_theta = one_vs_all(X, y, 1, 10)
for j in range(10):
    pick_one=np.random.randint(0, 5000)
    image = X[pick_one, :]
    data=predict(image,all_theta)
    data=list(data)
    max=0
    for i in range(1,len(data)):#将预测值转数字
        if(data[max]<data[i]):
            max=i
    print(y2[pick_one, :],end=" ")
    print(max+1)

输出

[1] 1
[8] 8
[2] 8
[10] 10
[5] 5
[9] 9
[5] 5
[10] 10
[2] 2
[9] 9

posted @ 2019-07-30 10:53  bigsmart  阅读(1048)  评论(0编辑  收藏  举报