吴恩达机器学习ex3:逻辑回归解决多分类

用逻辑回归解决多分类

多分类实际上就是二分类的拓展,需要训练多个分类器,最终选取分类出来概率最高的那个分类器就是预测结果。

用梯度下降算法优化最小函数求解多分类

import scipy.io as sio
import numpy as np
import matplotlib.pyplot as plt
def load_data():
    data = sio.loadmat("ex3data1.mat")
    X = data['X']#特征值
    Y = data['y']#结果值
    return X,Y#返回特征值和结果值
def random_show(X):#随机展示100张图片的函数
    m = X.shape[0]#样本数
    rand_index = np.random.randint(0,m,100)#随机生成0-m个整数
    rand_img = X[rand_index,:] #取出随机抽取的100张图片
    fig,ax = plt.subplots(figsize=(8,8),nrows=10,ncols=10,sharex=True,sharey=True)
    #nrows ncols表示生成多少行 多少列子图 figsize表示生成8,8英寸大小figure
    for i in range(10):
        for j in range(10):
            ax[i,j].imshow(rand_img[10*i+j].reshape(20,20).T,cmap="gray_r")
            #每张图片被拉升成一条直线 需要进行维度转换 变为20*20像素的图片 ax[i,j]表示取出第i行j列个子图
    plt.xticks([])#去除x轴刻度
    plt.yticks([])#去除y轴刻度
    plt.show()
def classifyData(Labelindex,y):
    for i in range(y.shape[0]):
        if y[i] == Labelindex:#如果结果是第i种分类器 则是正类 代表1
            y[i] = 1
        else:
            y[i] = 0#反之代表父类
    return y
def sigmoid(z):#定义激活函数
    return 1/(1+np.exp(-z))
def costfunction(X,y,theta,lamda):#代价函数
    m = X.shape[0]
    A = sigmoid(X@theta)
    first = y*np.log(A)
    second = (1-y)*np.log(1-A)
    res = np.sum(lamda*(np.power(theta[1:,0],2))/(2*m))#正则项
    return -np.sum(first+second)/m + res
def grad_decent(X,y,theta,lamda,learning_rate,num,index):#梯度下降 index参数代表这是第几个分类器
    m = X.shape[0]
    for i in range(num):
        A = sigmoid(X@theta)
        res = np.append(theta[1:,[0]],[[0]],axis=0)
        theta = theta - learning_rate*((X.T@(A-y))/m+res)
        cost = costfunction(X,y,theta,lamda)
        print("{}类别分类器,第{}次迭代,损失为{}".format(index,i,cost))
    return theta
def test(final_theta,X,Y):#验证训练结果函数
    m = X.shape[0]
    predict_result = sigmoid(X@final_theta.T)
    print(predict_result)
    max_index = np.argmax(predict_result,axis=1)#选取概率值最大的那个分类器
    count = 0
    for i in range(m):
        if max_index[i]+1 == Y[i]:#预测结果
            count = count+1
    print(count/m)
def main():
    X,Y=load_data()
    random_show(X)
    X = np.append(np.ones((5000, 1)), X, axis=1)
    final_theta = []
    for i in range(10):#总共需要训练十个分类器
        z = np.copy(Y)
        y = classifyData(i+1,z)#将标签类别 传进去 分正类跟父类
        thata = grad_decent(X, y, np.zeros((401, 1)), 0.1, 0.001, 1000, i+1)#梯度下降,训练分类器
        final_theta.append(thata.ravel())#将训练结果保存到变量中
    final_theta = np.array(final_theta)
    test(final_theta,X,Y)#验证训练集
if __name__ == '__main__':
    main()

运用api scipy.optimize模块的minimize函数求最优theta解决多分类

参数 fun:要优化的代价函数 Method:运用的优化算法
jac:梯度向量
x0:初始参数 只能为(n,)维 一维矩阵
method:要最小化代价函数的方法 这里采用的是’TNC’方法
args():其他参数 传递给最小化函数,jac的其他参数 这里传递特征值,真实标签值,lambda

import scipy.io as sio
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize
def load_data():#加载数据
    data = sio.loadmat("ex3data1.mat")
    X = data['X']#特征值
    Y = data['y']#结果值
    return X,Y#返回特征值和结果值
def random_show(X):#随机展示100张图片的函数
    m = X.shape[0]#样本数
    rand_index = np.random.randint(0,m,100)#随机生成0-m个整数
    rand_img = X[rand_index,:] #取出随机抽取的100张图片
    fig,ax = plt.subplots(figsize=(8,8),nrows=10,ncols=10,sharex=True,sharey=True)
    #nrows ncols表示生成多少行 多少列子图 figsize表示生成8,8英寸大小figure sharex sharey为了让图更好看
    for i in range(10):
        for j in range(10):
            ax[i,j].imshow(rand_img[10*i+j].reshape(20,20).T,cmap="gray_r")
            #每张图片被拉升成一条直线 需要进行维度转换 变为20*20像素的图片 ax[i,j]表示取出第i行j列个子图
    plt.xticks([])#去除x轴刻度
    plt.yticks([])#去除y轴刻度
    plt.show()
def sigmoid(z):#定义激活函数
    return 1/(1+np.exp(-z))
# 这里 theta参数变为了一维矩阵的形式 所以在costfunction、梯度计算的时候不同于之前自己写的梯度下降了 要微调一下矩阵乘法计算
def costfunction(theta,X,y,lamda):#代价函数
    m = X.shape[0]
    A = sigmoid(X@theta)
    first = y*np.log(A)
    second = (1-y)*np.log(1-A)
    res = np.sum(lamda*(np.power(theta[1:],2))/(2*m))#正则项
    return -np.sum(first+second)/m + res
def grad(theta,X,y,lamda):#梯度的计算
    m = X.shape[0]
    A = sigmoid(X@theta)
    jac = X.T@(A-y)/m
    res = lamda*np.insert(theta[1:],obj=0,values=0)/m#正则化项
    return jac+res#返回计算好的梯度
def test(X,y,final_theta):
    A = sigmoid(X@final_theta.T)
    max_index = np.argmax(A,axis=1)+1#要注意 这里返回的是预测最大的下标 下标是从0开始的 所以我们得全部+1
    print("最终精度为:{}".format(np.mean(max_index == y)))
    #np里true false形式矩阵 在求平均 就看成1 和 0 
def main():
    X,Y=load_data()
    random_show(X)
    X = np.append(np.ones((5000, 1)), X, axis=1)
    final_theta = []
    lamda = 0.1
    y = Y.ravel()#需要处理成一维矩阵形式 不然后面加减会维度不匹配
    for i in range(10):
        theta = np.zeros((401,))
        theta = minimize(fun=costfunction,args=(X,y==i+1,lamda),jac=grad,x0=theta,method='TNC')
        #这里用到了一个小技巧 也就是y==i+1 它会把是第i+1类的标签置为true 不是的则置为false
        #np矩阵 这种ture false矩阵与别的数进行加减运算 true会当作1 false当作0
        final_theta.append(theta.x)#theta.x就是优化好的参数分类器 加到final_theta里
    final_theta = np.array(final_theta)#变为二维矩阵
    test(X,y,final_theta)#将所有分类器放进去验证
if __name__ == '__main__':
    main()

你可能感兴趣的:(机器学习,#,吴恩达机器学习作业,python,机器学习)