EX3:逻辑回归实现手写数字识别(多类分类)

EX3:逻辑回归实现手写数字识别(多类分类)

1.读取数据

注意给出的数据集是以mat形式为后缀,在python中可以使用scipy.io中的函数loadmat()读取mat文件。

import numpy as np
from scipy.io import loadmat
data=loadmat('ex3data1.mat')

读取数据以后看一下data长什么样子:

​​​​​​{‘header’: b’MATLAB 5.0 MAT-file, Platform: GLNXA64, Created on: Sun Oct 16 13:09:09 2011’,
version’: ‘1.0’,
globals’: [],
‘X’: array([[0., 0., 0., …, 0., 0., 0.],
[0., 0., 0., …, 0., 0., 0.],
[0., 0., 0., …, 0., 0., 0.],
…,
[0., 0., 0., …, 0., 0., 0.],
[0., 0., 0., …, 0., 0., 0.],
[0., 0., 0., …, 0., 0., 0.]]),
‘y’: array([[10],
[10],
[10],
…,
[ 9],
[ 9],
[ 9]], dtype=uint8)}

可以看到data里面分为‘X’和y两个部分,作为输入数据和标签,分别看看它们的大小:

X:(5000,400),y:(5000,1)

所以数据集中包含5000个400维的特征向量,即每一个x都含有400个特征.
且y中含有1-10共10种标签。

2.Sigmoid函数

逻辑回归模型的假设函数中使用到Sigmoid函数,其公式为:
g ( z ) = 1 1 + e − z g(z)=\frac1{1+e^{-z}} g(z)=1+ez1
逻辑回归的假设函数为:
h θ ( x ) = 1 1 + e − θ T X h_{\theta}(x)=\frac1{1+e^{-\theta^T X}} hθ(x)=1+eθTX1

def sigmoid(z):
	return 1/(1+np.exp(-z))

3.代价函数

逻辑回归问题中的代价函数表述为:
J ( θ ) = 1 m ∑ i = 1 m − ( y ( i ) l o g ( h θ ( x ( i ) ) ) + ( 1 − y ) ( i ) l o g ( 1 − h θ ( x ( i ) ) ) ) J(\theta)=\frac1 m \sum\limits_{i=1}^m -(y^{(i)}log(h_{\theta}(x^{(i)}))+ (1-y)^{(i)}log(1-h_{\theta}(x^{(i)}))) J(θ)=m1i=1m(y(i)log(hθ(x(i)))+(1y)(i)log(1hθ(x(i))))

def cost(theta,X,y,alpha):
    m=X.shape[0]
    hthetax=sigmoid(X.dot(theta))
    return -alpha*(y.dot(np.log(hthetax))+(1-y).dot(np.log(1-hthetax)))/m

4.梯度

为了在拟合模型时使用Scipy库中的优化函数,要定义一个函数计算代价函数的梯度,公式为:
∂ ∂ θ i J ( θ ) = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x ( i ) \frac{\partial}{\partial \theta_i}J(\theta)= \frac1 m( h_{\theta}(x^{(i)})-y^{(i)})x^{(i)} θiJ(θ)=m1(hθ(x(i))y(i))x(i)
写成矩阵形式:
h θ ( X ) = X θ , s i z e : ( 5000 , 1 ) h θ ( X ) − y = X θ − y , s i z e : ( 5000 , 1 ) 返 回 值 s i z e = ( 400 , 1 ) ∴ ∂ ∂ θ i J ( θ ) = X T ( h θ ( X ) − y ) / m h_{\theta}(X)=X\theta,size:(5000,1) \\ h_{\theta}(X)-y=X\theta-y,size:(5000,1) \\ 返回值size=(400,1) \\ \therefore \frac{\partial}{\partial \theta_i}J(\theta)= X^T(h_{\theta}(X)-y)/m hθ(X)=Xθ,size:(5000,1)hθ(X)y=Xθy,size:(5000,1)size=(400,1)θiJ(θ)=XT(hθ(X)y)/m
根据上面推出的矩阵形式公式构建函数如下:

def grad(theta,X,y):
    m=X.shape[0]
    hthetax=sigmoid(X.dot(theta))
    return (X.T.dot(hthetax-y))/m

5.分类器构建

这次我们要利用逻辑回归来做的不是单纯的二分类而是十分类,根据视频课程中所说,我们可以对每一个数字都做一次二分类。

例如数字1,我将把所有手写数字图片分为是1和不是1两类,从而习得一组针对于数字1的分类权重,以此类推,我们可以最终习得十组分类权重从而组成一个分类器。

分类器构建过程解析如下:

  1. 初始化最终权重矩阵
  2. 构造输入数据矩阵X(添加偏置项)
  3. 对于1-10这十个数字,都初始化一个权重向量,利用优化函数来寻找最佳权重
  4. 将每一个数字得到的权重向量放入权重矩阵中
from scipy.optimize import minimize

def ten_classification(X,y):
    final_theta=np.zeros((10,X.shape[1]+1))#每一行都将是针对某一个数字的二分类权重向量(含偏置项)
    
    #为X添加偏置项
    ones_col=np.ones(X.shape[0])
    X=np.c_[ones_col,X]

    for i in range(1,11):
        theta=np.zeros(X.shape[1])
        #提取针对数字i的二分类器
        y_i=np.array([1 if label==i else 0 for label in y])
        
        #优化函数寻找theta
        result=minimize(fun=cost,x0=theta,args=(X,y_i),method='TNC',jac=grad)
        final_theta[i-1,:]=result.x
    return final_theta

为保证运算过程中矩阵维度的准确性,接下来分析一下分类器中各个量的大小:

  • final_theta.shape:(10,401)
  • X.shape:(5000,401)
  • theta.shape:(401,)
  • y.shape:(5000,)

6.分类器结果输出

调用分类器输出结果:

final_theta=ten_classification(data['X'],data['y'])

运行以上代码出现如下Warning,暂时还未解决:

  • RuntimeWarning: divide by zero encountered in log
    return -(y.dot(np.log(hthetax))+(1-y).dot(np.log(1-hthetax)))/m
  • RuntimeWarning: overflow encountered in exp
    return 1/(1+np.exp(-z))

7.分类结果评估

将得到的权重模型再次用于数据集X,将计算得到的结果和标签进行比较并得出准确率:

def predict_all(X,final_theta):
    #添加偏置
    ones_col=np.ones(X.shape[0])
    X=np.c_[ones_col,X]

    pre_max=np.argmax(sigmoid(X.dot(final_theta.T)),axis=1)#找出hthetax中最大的一个,为预测值-1
    return pre_max+1
y_pre=predict_all(data['X'],final_theta)
correct=np.array([1 if y_pre[i]==data['y'][i] else 0 for i in range(len(y_pre))])
accuracy=(correct.sum())/len(correct)
print('Accuracy:{}%'.format(accuracy*100))

输出为:Accuracy:97.42%

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值