Andrew Ng Machine Learning——Work(Three)——Mult-classification(Based on Python 3.7)

                    Python 3.7

所用数据集链接:多分类所用数据集(ex3data1.mat),提取码:c3yy

Mult-classification

题目:目前有一个矩阵文件,其中有5000个样本,每一个样本都是一张图像(20*20),图像上为0-9的某一个数字,现希望通过多分类算法训练使得机器能够识别出手写体对应数字

1.0 Package

先进包再说:

import numpy as np
# 数据处理
import pandas as pd
# 数据读取与加工,格式转换
import matplotlib.pyplot as plt
# 画图
from scipy.io import loadmat
# 这个第一次见,这是专门用来读取矩阵文件的函数(因为像素点是以矩阵文件格式保存的)
from scipy.optimize import minimize
# 高级优化函数(自从用这个以后再也不想自定义梯度下降)
1.1 Load data

第一步仍然是读取数据,代码如下:

def load_data(path):
# 定义函数,传入参数path
    data=loadmat(path)
# 读取path指定路径的矩阵文件
    x=data['X']
    y=data['y']
# 根据索引区分x,y
    return data,x,y
# 返回
data,x,y=load_data('ex3data1.mat')
#print(data)
print(x.shape)
# 查看x形状 (5000,400)
print(y.shape)
# 查看y形状 (5000,1)
print(np.unique(y))
# 去除y中重复元素看看y是什么样(其实就是看看一共分几类)

注意这里将每个样本拉直成一个400元素的向量(所以注意画图时候reshape以下) ,x矩阵如下:
X = [ ( x 1 ) T ( x 2 ) T ( x 5000 ) T ] X=\begin{bmatrix} (x^ {1})^{T} \\ (x^{2})^{T}\\ \vdots\\ (x^{5000})^{T} \end{bmatrix}
其中每个 x i x^{i} 是一个400维向量

1.2 Visualization data

接下来可视化数据,话说矩阵文件可视化还是第一次尝试,不过思路类似,先可视化200个看看,代码如下:

def view_data():
# 定义函数
    data_index=np.random.randint(0,5000,200)
# 在0到5000里随机取200个数,返回一个一维数组
    data_sample=x[data_index,:]
# 将上述数组作为索引,在数据中随机挑选200个样本  
    fig,ax=plt.subplots(nrows=20,ncols=10,sharex=True,sharey=True,figsize=(12,12))
# 创建画布,指定对象(ax),注意此时的对象是一个矩阵,所以调用时候和之前不太一样
    for i in range(20):
        for j in range(10):
            ax[i,j].matshow(data_sample[i+j*20].reshape((20,20)),cmap='gray_r')
# 将对象排列为20行10列,记得matshow里传入绘图对象时reshape
    plt.xticks([])
    plt.yticks([])
# 去掉标题,不然很难看
    plt.show()
# 可视化
#view_data()

输出如下:
在这里插入图片描述
一些奇奇怪怪的手写体灰度图,下面数据预处理。

1.3 Data preprocess

代码如下:

def data_preprocess(x,y,data):
# 定义函数,传入参数
    x = np.insert(x, 0, 1, axis=1)
# 第一列插一列1(为后续向量化)
    y = y.flatten()
# 把y展开成一维数组,原因后面会看到
    return x,y
x,y=data_preprocess(x,y,data)    
theta=np.zeros((x.shape[1]))
# 顺便初始化Theta
#print(theta[1])
#print(theta)
print(theta.shape)
1.4 Sigmoid function

然后就是sigmoid函数,代码如下:

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

下面进入算法核心阶段。

1.5 Regularized costfunction

先放图:
在这里插入图片描述
其中:
h θ ( x ) = 1 1 + e θ T x h_{\theta}(x)=\frac{1}{1+e^{\theta ^{T}x}}
θ \theta 为一个十维向量
代码如下:

def regularized_costfunction(theta,x,y,l):
# 定义函数
    h=x@theta
# 注意这里x为二维数组,theta为一维数组,相乘后返回的是一维数组
    J=(-y)*np.log(sigmoid(h))-(1-y)*np.log(1-sigmoid(h))
# 所以说要在前面把y展开成一维数组,是为了和h计算时方便(因为h是一维数组)
    reg=theta[1:]@theta[1:]
# 仍然是那句话,theta_{0}不用正则化
    cost=sum(J)/len(x)+reg*l/(2*len(x))
    return cost
# 返回
cost=regularized_costfunction(theta,x,y,1)
# 此时的cost似乎是-17.05左右
1.6 Regularized gradient

先放图:
在这里插入图片描述
注意正则化从 θ 1 \theta_{1} 开始
代码如下:

def regularized_gradient(theta,x,y,l):
# 定义函数
    h=x@theta
    G=x.T@(sigmoid(h)-y)
# 这些都一样
    reg=theta[1:]
    reg=np.insert(reg,0,1,axis=0)
# 这里之所以插入0是因为这里的reg是矩阵(或者说数组),而代价函数里是一个常数(两个向量相乘)
    gradient=G/len(x)+reg*l/len(x)
    return gradient
# 返回梯度,一个数组
1.7 Train model

终于要开始训练模型了,(这里是依次训练每一个逻辑回归器,再将它们分别的权重放在一个矩阵中),代码如下:

def training(x,y,l,c):
# 定义函数,这里c为总类数(10)
    all_theta=np.zeros((c,x.shape[1]))
# 这个all_theta为(10,400),将来会装每一个分类器的权重
    for i in range(1,c+1):
        theta=np.zeros(x.shape[1])
        y_i=np.array([1 if label ==i else 0 for label in y])
#  返回一个列表,寻找某一类样本的位置       
        result=minimize(fun=regularized_costfunction,x0=theta,args=(x,y_i,l),method='TNC',jac=regularized_gradient)
# 返回每一个样本的theta
        all_theta[i-1,:]=result.x
# 加入到all_theta中
    return all_theta
1.8 Model predict

开始利用模型预测:

def model_predict(x, all_theta):   
# 定义函数
    h = sigmoid(x @ all_theta.T)
# 计算每一个样本在每一个分类器里的可能性(也就是属于每一个类的可能性)
    h_arg = np.argmax(h, axis=1)
# 概率最大的那个就是对应类
    h_arg = h_arg + 1 
# 加一是因为Python索引从0开始
    return h_arg
1.9 Evalute model

看看预测结果怎么样:

all_theta = training(x, y, 1, 10)
# 返回theta矩阵
print('fin_theta:',all_theta)
def evalute_model(theta,x,y):
# 定义函数
    y_pred = model_predict(x, theta)
# 返回模型预测列表
    accuracy = [ 1 if i==j else 0 for (i,j) in zip (y_pred,y)]
# 返回列表,其中1表示预测准确(即预测标签和实际标签相符),0表示预测错误
    accuracy= np.mean(accuracy)
# 计算精度
    print ('accuracy = {0}%'.format(accuracy * 100))
evalute_model(all_theta,x,y)

输出如下:
在这里插入图片描述
已经很好了,再高就该注意是不是过拟合了(把 λ \lambda 设为0,就能看到准确率在97%+,显然是出现了过拟合)

1.10 All

最后,给出完整代码:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.io import loadmat
from scipy.optimize import minimize
def load_data(path):
    data=loadmat(path)
    x=data['X']
    y=data['y']
    return data,x,y
data,x,y=load_data('ex3data1.mat')
#print(data)
print(x.shape)
print(y.shape)
#print(np.unique(y))
def view_data():
    data_index=np.random.randint(0,5000,200)
    data_sample=x[data_index,:]
    fig,ax=plt.subplots(nrows=20,ncols=10,sharex=True,sharey=True,figsize=(12,12))
    for i in range(20):
        for j in range(10):
            ax[i,j].matshow(data_sample[i+j*20].reshape((20,20)),cmap='gray_r')
    plt.xticks([])
    plt.yticks([])
    plt.show()
view_data()
def data_preprocess(x,y,data):
    x = np.insert(x, 0, 1, axis=1)
    y = y.flatten()
    return x,y
x,y=data_preprocess(x,y,data)    
theta=np.zeros((x.shape[1]))
#print(theta[1])
#print(theta)
print(theta.shape)
def sigmoid(z):
    return 1/(1+np.exp(-z))
def regularized_costfunction(theta,x,y,l):
    h=x@theta
    J=(-y)*np.log(sigmoid(h))-(1-y)*np.log(1-sigmoid(h))
    reg=theta[1:]@theta[1:]
    cost=sum(J)/len(x)+reg*l/(2*len(x))
    return cost
cost=regularized_costfunction(theta,x,y,1)
print('cost:',cost)
def regularized_gradient(theta,x,y,l):
    h=x@theta
    G=x.T@(sigmoid(h)-y)
    reg=theta[1:]
    reg=np.insert(reg,0,1,axis=0)
    gradient=G/len(x)+reg*l/len(x)
    return gradient
def training(x,y,l,c):
    all_theta=np.zeros((c,x.shape[1]))
    for i in range(1,c+1):
        theta=np.zeros(x.shape[1])
        y_i=np.array([1 if label ==i else 0 for label in y])
        result=minimize(fun=regularized_costfunction,x0=theta,args=(x,y_i,l),method='TNC',jac=regularized_gradient)
        all_theta[i-1,:]=result.x
    return all_theta
def model_predict(x, all_theta):   
    h = sigmoid(x @ all_theta.T)
    h_arg = np.argmax(h, axis=1)
    h_arg = h_arg + 1 
    return h_arg
all_theta = training(x, y, 1, 10)
print('fin_theta:',all_theta)

def evalute_model(theta,x,y):
    y_pred = model_predict(x, theta)
    accuracy = [ 1 if i==j else 0 for (i,j) in zip (y_pred,y)]
    accuracy= np.mean(accuracy)
    print ('accuracy = {0}%'.format(accuracy * 100))
evalute_model(all_theta,x,y)

这里模型应用的画需要一张图片,然后处理成20*20的灰度图像输进去看效果。

未经允许,请勿转载。

欢迎交流。

原创文章 19 获赞 187 访问量 8万+

猜你喜欢

转载自blog.csdn.net/PRINCE2327/article/details/106033434