机器学习练习3-多类别逻辑回归和前馈神经网络

机器学习练习3-多类别逻辑回归和前馈神经网络,第1张

本文基于Andrew_Ng的ML课程作业 1-Logistic Regression in multi-class classification problem:One_vs_All Classifier:使用一对一全分类方法,有k个不同类的标签就有k个分类器,每个分类器在"类别i"和"不是i"之间决定;我们把分类器训练包含在一个函数中,该函数计算10个分类器中的每个分类器的权重,最终实现手写数字0~9的识别

导入库

import numpy as np
import  matplotlib.pyplot as plt
from scipy.io import loadmat
import scipy.optimize as opt
from sklearn.metrics import classification_report

函数:Sigmoid函数

def sigmoid(z): #Sigmoid函数
    return 1/(1+np.exp(-z))

函数:计算正则化的代价函数J(theta)

def computeRegCost(theta,X,y,lambada): #计算正则化的代价函数J(theta)
    theta=np.matrix(theta)
    X=np.matrix(X)
    y=np.matrix(y)
    first=np.multiply(-y,np.log(sigmoid(X*theta.T)))
    second=np.multiply((1-y),np.log(1-sigmoid(X*theta.T)))
    reg=(lambada/(2*len(X)))*np.sum(np.power(theta[:,1:theta.shape[1]],2))  #matrix[:,1:matrix.shape[1]]:取矩阵的第一列直到最后一列(左闭右闭)
    return np.sum(first-second)/len(X)+reg

 函数:计算正则化的梯度grad

def computeRegGradient(theta,X,y,lambada): #计算正则化的梯度grad
    theta = np.matrix(theta)
    X = np.matrix(X)
    y = np.matrix(y)
    parameters=int(theta.ravel().shape[1])
    grad = np.zeros(parameters)
    error=(sigmoid(X*theta.T))-y
    for i in range(parameters):
        term=np.multiply(error,X[:,i])
        if (i==0):  #theta_0的梯度单独更新
            grad[i]=np.sum(term)/len(X)
        else:
            grad[i]=np.sum(term)/len(X)+(lambada/len(X))*theta[:,i]
    return grad

 函数:一对多分类器

def one_vs_all(X,y,num_labels,lambada): #一对多分类器
    rows=X.shape[0]
    parameters=X.shape[1]+1
    all_theta=np.zeros((num_labels,parameters)) #num_labels=10,10个分类器各自有all_theta的一行
    X=np.insert(X,0,values=np.ones(rows),axis=1)
        #a=np.insert(arr,obj,values= ,axis= ): arr:原始数组;obj:插入元素位置;values:插入内容;axis=0按行插入,axis=1按列插入
        #np.ones:用法同np.zeros
    for i in range(1,num_labels+1):
        theta=np.zeros(parameters)
        y_i=np.array([1 if label==i else 0 for label in y]) #对每个分类器,遍历y,将y从类标签转换为每个分类器的二进制值(是类i/不是类i)并将这些二进制值存储在y_i中
        y_i=np.reshape(y_i,(rows,1))    #相当于将y_i转置
        fmin=opt.fmin_tnc(func=computeRegCost,x0=theta,fprime=computeRegGradient,args=(X,y_i,lambada))
        all_theta[i-1,:]=fmin[0]
    return all_theta

函数:预测函数

def predict_all(X,all_theta):   #预测函数
    rows=X.shape[0]
    X=np.insert(X,0,values=np.ones(rows),axis=1)
    X=np.matrix(X)
    all_theta=np.matrix(all_theta)
    h=sigmoid(X*all_theta.T)
        #X(5000*400),all_theta(10*400)--X*all_theta.T(5000*10)--h(5000*10):h[i,j]表示X中的第i个数据为第j类(数字j)的概率
            # 取二维数组和矩阵中的数字
             #data = np.array([[1, 2, 3], [4, 5, 6]]);print(data[0][1])
             #data = np.matrix(data);print(data[0, 1])
    h_argmax=np.argmax(h,axis=1)
        #np.argmax(array([ ])):取出array中元素最大值对应的索引(默认从0开始)
        #np.argmax(array([[ ],[ ]]),axis= ): axis=1:按行方向取出array中元素最大值对应的索引;axis=0:按列方向
    h_argmax=h_argmax+1 #这里得到的h_argmax即为y_pred:分类器返回的预测值
    return h_argmax

主函数:

#Logistic Regression in multi-class classification problem:One_vs_All Classifier
#使用一对一全分类方法,有k个不同类的标签就有k个分类器,每个分类器在"类别i"和"不是i"之间决定
#我们把分类器训练包含在一个函数中,该函数计算10个分类器中的每个分类器的最终权重

data=loadmat('ex3data1.mat')    #用Python读取MATLAB格式的.m文件
#data['X'].shape=(5000, 400),data['y'].shape=(5000, 1):5000个数据,每个数据有400个像素,每个像素都是影响该数据为某个数字的因素

#随机展示100个数据
sample_index=np.random.choice(np.arange(data['X'].shape[0]),100)
    #np.random.choice(a,size=None,replace=True,p=None):从一维数据a中随机抽取数字,返回指定size的数组
    #replace:True表示可以取相同数字,False表示不可以取相同数字; 数组p:与数组a对应,表示取数组a中每个元素的概率,默认概率相同
sample_images=data['X'][sample_index,:]   #取所有列的sample_idx行
fig,ax_array=plt.subplots(nrows=10,ncols=10,sharex=True,sharey=True,figsize=(12,12))
    #plt.subplots(nrows=1,ncols=1,sharex=False,sharey=False,squeeze=True,subplot_kw=None,gridspec_kw=None,**fig_kw):
    #nrows,ncols:子图行列数; sharex,sharey设置为True时,所有子图共享x,y轴; **fig_kw:所有其他关键字参数传递给figure()调用
for row in range(10): #range(start,stop,step):[start,stop);start省略时从0开始计数,step省略时步长为1
    for col in range(10):   #遍历确保对每一个[row,col]的子图都进行修改
        ax_array[row,col].matshow(sample_images[10*row+col].reshape((20,20)).T,cmap='gray_r')
            #plt.matshow(matrix,cmap= ):绘制矩阵,一个矩阵元素对应一个图像像素
            #100个数据,每个数据是20*20像素的数字灰度图像,每个像素用一个浮点数表示该位置的灰度强度,20*20的像素网格被展开成一个400维的向量
            #a.reshape(m,n):将原数组a转化为一个m行n列的新数组,a自身不变;((m,n))表示转化为矩阵
            #.T将图像翻转,否则图像不正立显示
            #cmap='gray_r':白底黑字 (gray:黑底白字)
        plt.xticks([])  #去掉x轴刻度
        plt.yticks([])  #去掉y轴刻度
plt.show()

labels=np.unique(data['y']) #np.unique():去除数组中的重复数字,顺序排序后输出
num_labels_real=len(labels)
all_theta=one_vs_all(data['X'],data['y'],num_labels_real,1)
y_pred=predict_all(data['X'],all_theta)
print(classification_report(data['y'],y_pred))
    #classification_report(y_true,y_pred):显示主要分类指标的文本报告,包括每个类的精确度P、召回率R、F1值(2/F1=1/P+1/R)
    #y_true:1维数组,目标值;y_pred:1维数组,分类器返回的预测值
    #输出:
    #精确度P:对类别n,实际为类别n与预测为类别n的比例
    #召回率R:对类别n,预测为类别n与实际为类别n的比例
    #F1值(2/F1=1/P+1/R):精确度和召回率都高时,F1值也会高;F1值在1时达到最佳值(完美的精确度和召回率),最差为0
    #accuracy:准确率,也即正确预测样本量与总样本量的比值
    #macro avg:宏平均,所有类别对应指标的平均值
    #weighted avg:带权重平均,类别样本占总样本的比重与对应指标的乘积的累加和

随机展示的100个数据

主要分类指标的文本报告 

2-Feedforward Neural Network:在现有权重基础上实现前馈神经网络来识别手写数字

导入库

import numpy as np
from scipy.io import loadmat
from sklearn.metrics import classification_report

函数:Sigmoid函数

def sigmoid(z): #Sigmoid函数
    return 1/(1+np.exp(-z))

主函数:

#Feedforward Neural Network:在现有权重基础上实现前馈神经网络来识别手写数字
#Iuput layer:20*20像素的图片有400个输入层单元(不包括额外添加的常数项)
#Hidden Layer(25),theta1和Output Layer(10),theta2均已提供

data=loadmat("ex3data1.mat")
weight=loadmat("ex3weights.mat")
theta1,theta2=weight['Theta1'],weight['Theta2']
X=np.matrix(np.insert(data['X'],0,values=np.ones(data['X'].shape[0]),axis=1))
y=np.matrix(data['y'])
#theta1.shape=(25,401) theta2.shape=(10,26)
#X.shape=(5000,401) y.shape=(5000,1)

#前馈神经网络模型
a1=X
z2=a1*theta1.T
a2=sigmoid(z2)
a2=np.insert(a2,0,values=np.ones(a2.shape[0]),axis=1)
z3=a2*theta2.T
a3=sigmoid(z3)
y_pred=np.argmax(a3,axis=1)+1
print(classification_report(y,y_pred))

现有模型(提供)

 主要分类指标的文本报告

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/715592.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-25
下一篇 2022-04-25

发表评论

登录后才能评论

评论列表(0条)

保存