SpringApplication 机器学习 NTFS权限 loops magento webforms vue表单 vue图表 bootstrap管理系统模板 pmp教学视频 jq选择子元素 pip环境变量配置 Navicat python随机函数 python3教程 python怎么下载安装 java时间 java继承关键字 javalist java循环语句 java环境包 java数组输出 java获得当前日期 java怎么输出数组 火牛软件 快点蛆虫成就单刷 idea重命名快捷键 视频字幕提取器 通讯录管理系统 win10有哪些版本 iar下载 掌门一对一下载 中维高清监控系统安装 3d看图软件 保留小数点后两位 华为动态照片 pro换肤 深入解析windows操作系统 黑客攻防技术宝典 Mapper
当前位置: 首页 > 学习教程  > 编程语言

机器学习作业3编程作业:Multi-class Classification and Neural Networks

2020/11/4 13:58:32 文章标签:

英文文档图片均来自原档作业pdf截图 网址https://www.coursera.org/learn/machine-learning/programming/8f3qT/linear-regression* 1 Multi-class Classification 数据集文件ex3data1.mat 是mat格式,首先将X,y导入到Python中: 在python中…

英文文档图片均来自原档作业pdf截图 网址https://www.coursera.org/learn/machine-learning/programming/8f3qT/linear-regression*

1 Multi-class Classification

在这里插入图片描述

数据集文件ex3data1.mat 是mat格式,首先将X,y导入到Python中:
在这里插入图片描述

在python中可以使用 scipy.io 中的函数 loadmat() 读取mat文件,函数savemat保存文件。
*读取出来的data是字典格式,可以通过函数type(data)查看。

c,s=np.unique(b,return_index=True) 唯一值
return_index=True表示返回新列表元素在旧列表中的位置,并以列表形式储存在s中

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import scipy.special
from scipy.io import loadmat

path = r'D:\Ninachen\wg_machinelearning\machine-learning-ex3\ex3\ex3data1.mat'
data = loadmat(path) # dict
X = data['X'] # ndarray
y = data['y']
sor_num = np.unique(y).shape[0] #类别数

打印一张图片试试看:
函数plt.imshow(img)
img为图片像素的矩阵array
灰度图:ax.imshow(img, cmap=plt.cm.gray)

def PrintAnImage(X, num):  #num 为图片序号, 即X的第几行所代表的的图片
    img = X[num,:].reshape((20,20))
    fig = plt.figure(figsize=(1,1)) # figure zise
    plt.imshow(img, cmap=plt.cm.gray)
    plt.axis('off')
    plt.show()

批量打印100张图片:PrintRandom100Image(X)
1.subplots参数以及figure参数 :
https://blog.csdn.net/zxyhhjs2017/article/details/81152780
2.调整子图间距:https://blog.csdn.net/qq_33039859/article/details/79424858
plt.subplots_adjust(left=None, bottom=None, right=None, top=None,wspace=None, hspace=None)
plt.tight_layout()
3.利用random.sample()和range()函数,可以很方便的实现在指定范围内随机生成指定多个不重复数字。https://blog.csdn.net/mnpy2019/article/details/98852241

import random
def PrintRandom100Image(X):  # 随机打印其中100张图片
    # 创建10行10列子图
   #  fig, ax = plt.subplots(nrows=10, ncols=10, sharey=True, sharex=True,figsize = (5,5), )
   #  plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
    fig = plt.figure(figsize=(6,6))
    lis = random.sample(range(5000), 100) # 随机选取100个图片的序号,即X的行号
    font = {'family': 'Times New Roman','weight': 'normal','size': 8} # 坐标轴字体
    for i in range(100):
        ax = fig.add_subplot(10, 10, i+1)
        img = X[lis[i], :].reshape((20, 20))
        plt.imshow(img, cmap=plt.cm.gray)
        # plt.axis('off')
        plt.xticks([])
        plt.yticks([])
        plt.xlabel('sample'+ str(lis[i]), font) # 标出每张图的序号
        # plt.subplots_adjust(wspace=0, hspace=-0.05) # 如果要去除图片之间的间隙
    plt.tight_layout() # 调整子图间距
    plt.show()

打印两次看看:
在这里插入图片描述

在这里插入图片描述

向量化,前面作业1、2也是已经运用矩阵来计算了的。
即这种形式:在这里插入图片描述
X为m*n维矩阵(m为数据个数,n为特征维数),θ矩阵为(n+1)维列向量。

梯度、cost都是矩阵运算:
在这里插入图片描述
在这里插入图片描述
多元分类器:即对K类,有K个分类器,对每个待分类的样本,会有一个K维的结果,每一维代表对该类的接近程度,得分(概率)最高的那一类就是样本归属的类别。
在这里插入图片描述
本来想用sklearn 结果发现没有python3.9版本的。。。
statsmodels里的logit试了下不行,有溢出报错,可能是输入维数太多了?

再把之前写的cost、梯度函数搬出来:(这里因为后面minimize要求theta向量是一维的,我之前写的cost和gradient把theta作二维的来用,所以要在函数里面加一条 把它reshape成二维)

import scipy.special

def sigmoid(x):
      return scipy.special.expit(x)   #return 1 / (1 + exp(-inx))

def cost(theta, X, y, lam): #即代价函数J(θ)
    theta2 = theta.reshape((theta.shape[0],1)) #
    J = np.sum(- np.multiply(y, np.log(sigmoid(X @ theta2)+ 1e-5)) - np.multiply((1 - y), np.log(1 - sigmoid(X @ theta2)+ 1e-5)))  # y.shape(1,m) 要转置成列向量
    second = lam / 2 * (np.sum(np.power(theta2,2)) - np.power(theta2[-1],2))
    second = second[0]
    return (J + second) / len(X)

def gradient(theta, X, y, lam):
    theta2 = theta.reshape((theta.shape[0], 1))  #
    gra_ori = (X.T @ (sigmoid(X @ theta2) - y))/len(X) #未正则化的
    regu = lam / len(X) * theta2
    regu[-1] = 0
    return (gra_ori + regu).ravel() #
    # 返回的theta为列向量

用scipy.optimize的minimize函数(代价cost函数最小)。

编写ClassificationSingle(X, y, lam, k)函数,是一元分类器,返回y等于k时,这一类的分类器对应的theta一维向量

这里有个疑问, 为什么在Minimize中method='TNC’使用了会报错。先把它去了,程序得以正常运行

def ClassificationSingle(X, y, lam, k): #返回 theta列向量
    # k = 10, 1, 2, 3, ... 9
    # type(X)= ndarray
    y = np.array([1 if label == k else 0 for label in y]) # 更新为只有0,1项
    y = y.reshape((y.shape[0],1)) # 二维
    theta = np.zeros(X.shape[1]) # 对应第k类判别函数的 系数向量 #一维
    # x0 (初始猜测值)必须是一维的:
    result = minimize(fun=cost, x0=theta, args=(X, y, lam),  jac=gradient, options={'disp': True})
#去掉 method='TNC'后不报错

    return result.x  # x是一维的

编写训练函数Prediction(X, y, lam, sample_x),X,y是训练数据和标签,lam是正则项系数λ,sample_x是待预测的数据(矩阵ndarray)

*因为:原数据集X对应的y,y的取值是10,1,2,3,…9; 其中1,2,3,…9都对应的是相应手写数字,“10”对应的是手写数字0的图片(无语,我最后才发现),所以我还要对y=10(其实是对应数字0这种情况)做一个调整。

其中h = sigmoid(sample_x @ theta_all) 实际是建立了一个10列的评分表,所以取最大的那个就是最后结果了。要注意位置和对应数字的关系即可。

def Prediction(X, y, lam, sample_x): #sample_x以ndarry类型
    sor_num = np.unique(y).shape[0]  # 类别数 : 10  =(k+1)
    theta_all = np.zeros((X.shape[1] + 1, sor_num))  # 建立一个矩阵以存放(k+1)组theta系数。 X.shape[1]+1行,(k+1)列

    X = np.insert(X, X.shape[1], values=1, axis=1)  # 常数项
    for i in range(0,10):  # y= 1, 2, ..., 10(0)
        if i != 0:
            theta_all[:,i] = ClassificationSingle(X, y, lam, i)
        else: # 即i=0  (数据y中标记的是10)
            theta_all[:,i] = ClassificationSingle(X, y, lam, 10)

    sample_x = np.insert(sample_x, sample_x.shape[1], values=1, axis=1) # 添加常数列
    h = sigmoid(sample_x @ theta_all) # h是评分表 sample_x.shape[0]行,(k+1)列
    predic = np.zeros(sample_x.shape[0])
    for i in range(sample_x.shape[0]):
            predic[i] = np.argmax(h[i])  # 位置即为对应数字
            # print (predic[i])
    return predic

在之前的随机打印100张的函数基础上,把预测结果也加上去:

def Judgement(y, predic): # 计算准确率
    y[np.where(y==0)] = 0  # 先将y中写成10的标成0(因为本来就是对应数字0,也与predic匹配)
    result = y - predic.reshape(predic.shape[0],1)
    # 不为0的项(即不相等)就是判断错误的
    correct = np.sum(result == 0)
    return correct / y.shape[0]

def PrintRandom100ImageWithPredict(sample_x, predic, title):  # 随机打印其中100张图片并标注预测结果
    # 创建10行10列子图
   #  fig, ax = plt.subplots(nrows=10, ncols=10, sharey=True, sharex=True,figsize = (5,5), )
   #  plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
    fig = plt.figure(figsize=(6,6))
    fig.suptitle('Prediction with the precision rate is:'+ str(title*100) +'%') #总标题
    lis = random.sample(range(5000), 100) # 随机选取100个图片的序号,即X的行号
    font = {'family': 'Times New Roman', 'weight': 'normal', 'size': 8}  # 坐标轴字体
    for i in range(100):
        ax = fig.add_subplot(10, 10, i+1)
        img = sample_x[lis[i], :].reshape((20, 20))
        plt.imshow(img, cmap=plt.cm.gray)
        plt.xticks([])
        plt.yticks([])
        plt.xlabel('this is:' + str(int(predic[lis[i]])), font)
        # plt.subplots_adjust(wspace=0, hspace=-0.05) # 如果要去除图片之间的间隙
    plt.tight_layout()  # 调整子图间距
    plt.show()

整合代码:

# multi-class classification
'''
1.画出图片图像
2.构建二分分类器
3.基于2构建多元分类器

'''
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from scipy.io import loadmat
import random
import scipy.special
from scipy.optimize import minimize

def sigmoid(x):
      return scipy.special.expit(x)   #return 1 / (1 + exp(-inx))

def cost(theta, X, y, lam): #即代价函数J(θ)
    theta2 = theta.reshape((theta.shape[0],1)) #
    J = np.sum(- np.multiply(y, np.log(sigmoid(X @ theta2)+ 1e-5)) - np.multiply((1 - y), np.log(1 - sigmoid(X @ theta2)+ 1e-5)))  # y.shape(1,m) 要转置成列向量
    second = lam / 2 * (np.sum(np.power(theta2,2)) - np.power(theta2[-1],2))
    second = second[0]
    return (J + second) / len(X)

def gradient(theta, X, y, lam):
    theta2 = theta.reshape((theta.shape[0], 1))  #
    gra_ori = (X.T @ (sigmoid(X @ theta2) - y))/len(X) #未正则化的
    regu = lam / len(X) * theta2
    regu[-1] = 0
    return (gra_ori + regu).ravel() #
    # 返回的theta为列向量

# X 每一行是一张图的400个数值,代表了20*20图片的每一个像素点
# 用.reshape((a,b))转化为20*20的矩阵
def PrintAnImage(X, num):  #num 为图片序号, 即X的第几行所代表的的图片
    img = X[num,:].reshape((20,20))
    fig = plt.figure(figsize=(2,2))
    plt.imshow(img, cmap=plt.cm.gray)
    plt.axis('off')
    plt.show()

def PrintRandom100Image(X):  # 随机打印其中100张图片
    # 创建10行10列子图
   #  fig, ax = plt.subplots(nrows=10, ncols=10, sharey=True, sharex=True,figsize = (5,5), )
   #  plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
    fig = plt.figure(figsize=(6,6))
    lis = random.sample(range(5000), 100) # 随机选取100个图片的序号,即X的行号
    font = {'family': 'Times New Roman','weight': 'normal','size': 8} # 坐标轴字体
    for i in range(100):
        ax = fig.add_subplot(10, 10, i+1)
        img = X[lis[i], :].reshape((20, 20))
        plt.imshow(img, cmap=plt.cm.gray)
        # plt.axis('off')
        plt.xticks([])
        plt.yticks([])
        plt.xlabel('sample'+ str(lis[i]), font) # 标出每张图的序号
        # plt.subplots_adjust(wspace=0, hspace=-0.05) # 如果要去除图片之间的间隙
    plt.tight_layout() # 调整子图间距
    plt.show()

def PrintRandom100ImageWithPredict(sample_x, predic, title):  # 随机打印其中100张图片并标注预测结果
    # 创建10行10列子图
   #  fig, ax = plt.subplots(nrows=10, ncols=10, sharey=True, sharex=True,figsize = (5,5), )
   #  plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
    fig = plt.figure(figsize=(6,6))
    fig.suptitle('Prediction with the precision rate is:'+ str(title*100) +'%') #总标题
    lis = random.sample(range(5000), 100) # 随机选取100个图片的序号,即X的行号
    font = {'family': 'Times New Roman', 'weight': 'normal', 'size': 8}  # 坐标轴字体
    for i in range(100):
        ax = fig.add_subplot(10, 10, i+1)
        img = sample_x[lis[i], :].reshape((20, 20))
        plt.imshow(img, cmap=plt.cm.gray)
        plt.xticks([])
        plt.yticks([])
        plt.xlabel('this is:' + str(int(predic[lis[i]])), font)
        # plt.subplots_adjust(wspace=0, hspace=-0.05) # 如果要去除图片之间的间隙
    plt.tight_layout()  # 调整子图间距
    plt.show()

def ClassificationSingle(X, y, lam, k): #返回 theta列向量
    # k = 10, 1, 2, 3, ... 9
    # type(X)= ndarray
    y = np.array([1 if label == k else 0 for label in y]) # 更新为只有0,1项
    y = y.reshape((y.shape[0],1))
    theta = np.zeros(X.shape[1]) # 对应第k类判别函数的 系数向量 #一维
    # x0 (初始猜测值)必须是一维的:
    result = minimize(fun=cost, x0=theta, args=(X, y, lam),  jac=gradient, options={'disp': True})
#去掉 method='TNC'后不报错

    return result.x  # x是一维的

def Prediction(X, y, lam, sample_x): #sample_x以ndarry类型
    sor_num = np.unique(y).shape[0]  # 类别数 : 10  =(k+1)
    theta_all = np.zeros((X.shape[1] + 1, sor_num))  # 建立一个矩阵以存放(k+1)组theta系数。 X.shape[1]+1行,(k+1)列
    X = np.insert(X, X.shape[1], values=1, axis=1)  # 常数项
    for i in range(0,10):  # y= 1, 2, ..., 10(0)
        if i != 0:
            theta_all[:,i] = ClassificationSingle(X, y, lam, i)
        else: # 即i=0  (数据y中标记的是10)
            theta_all[:,i] = ClassificationSingle(X, y, lam, 10)

    sample_x = np.insert(sample_x, sample_x.shape[1], values=1, axis=1) # 添加常数列
    h = sigmoid(sample_x @ theta_all) # h是评分表 sample_x.shape[0]行,(k+1)列
    predic = np.argmax(h, axis=1)
    return predic # 一维

def Judgement(y, predic): # 计算准确率
    y[np.where(y==0)] = 0  # 先将y中写成10的标成0(因为本来就是对应数字0,也与predic匹配)
    result = y - predic.reshape(predic.shape[0],1)
    # 不为0的项(即不相等)就是判断错误的
    correct = np.sum(result == 0)
    return correct / y.shape[0]


path = r'D:\Ninachen\wg_machinelearning\machine-learning-ex3\ex3\ex3data1.mat'
data = loadmat(path) # dict
X = data['X'] # ndarray  训练集
y = data['y'] # 分类标签
sample_x = X.copy()  # 待测试数据集
lam = float(input('please input lambda:'))

# PrintRandom100Image(X) # 随机打印100张图
# 修改PrintRandom100Image(X)函数 (添加预测出的结果)
predic = Prediction(X, y, lam, sample_x)
PrintRandom100ImageWithPredict(sample_x, predic, Judgement(y, predic))

结果:
lambda=0
在这里插入图片描述

2 Neural Networks

Feedforward Propagation and Prediction
在这里插入图片描述
此例中1输入层,1隐含层,1输出层

每个节点用a表示。简单来说,每个节点相当于 前一层节点(再加上常数1)用θ加权之和 再使用激活函数 得到的结果。

在这里插入图片描述
根据已经提供的ex3weights.mat文件中的权重theta1与theta2,来完成神经网络模型:

在这里插入图片描述
即隐含层有26个节点

def Prediction_FFNN(X, theta1, theta2):
    # a1 = X  输入层
    X = np.insert(X, 0, values=1, axis=1) # 添加常数列
    a2 = sigmoid(X@theta1) # 隐含层
    a2 = np.insert(a2, 0, values=1, axis=1) # 添加常数列
    a3 = sigmoid(a2@theta2) # 输出层
    predic = np.argmax(a3, axis=1) + 1 # 对应数字
    predic[np.where(predic == 10)] = 0 # 将10改成0
    return  predic

和多元分类器一样画图, 整合一下代码:

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from scipy.io import loadmat
import random
import scipy.special

def sigmoid(x):
      return scipy.special.expit(x)   #return 1 / (1 + exp(-inx))

def PrintRandom100ImageWithPredict(sample_x,predic):  # 随机打印其中100张图片并标注预测结果
    # 创建10行10列子图
    fig = plt.figure(figsize=(6,6))
    # fig.suptitle('Prediction with the precision rate is:'+ str(title*100) +'%') #总标题
    lis = random.sample(range(5000), 100) # 随机选取100个图片的序号,即X的行号
    font = {'family': 'Times New Roman', 'weight': 'normal', 'size': 8}  # 坐标轴字体
    for i in range(100):
        ax = fig.add_subplot(10, 10, i+1)
        img = sample_x[lis[i], :].reshape((20, 20))
        plt.imshow(img, cmap=plt.cm.gray)
        plt.xticks([])
        plt.yticks([])
        plt.xlabel('this is:' + str(int(predic[lis[i]])), font)
        # plt.subplots_adjust(wspace=0, hspace=-0.05) # 如果要去除图片之间的间隙
    plt.tight_layout()  # 调整子图间距
    plt.show()

def Prediction_FFNN(X, theta1, theta2):
    # a1 = X  输入层
    X = np.insert(X, 0, values=1, axis=1) # 添加常数列
    a2 = sigmoid(X@theta1) # 隐含层
    a2 = np.insert(a2, 0, values=1, axis=1) # 添加常数列
    a3 = sigmoid(a2@theta2) # 输出层
    predic = np.argmax(a3, axis=1) + 1 # 对应数字
    predic[np.where(predic == 10)] = 0 # 将10改成0
    return  predic

path = r'D:\Ninachen\wg_machinelearning\machine-learning-ex3\ex3\ex3data1.mat'
data = loadmat(path) # dict
X = data['X'] # ndarray  训练集
y = data['y'] # 分类标签 y.shape=(5000,1)
y[np.where(y==10)] = 0 # 将10改成0
path2 = r'D:\Ninachen\wg_machinelearning\machine-learning-ex3\ex3\ex3weights.mat'
data2 = loadmat(path2) # dict
theta1 = data2['Theta1'].T
theta2 = data2['Theta2'].T
predic = Prediction_FFNN(X, theta1, theta2) # predic.shape=(5000,)
y = y.ravel()
c_rate = np.mean(predic==y) # 准确率
print('the precision rate is', c_rate*100, '%')
PrintRandom100ImageWithPredict(X,predic)

注意predic和y的维度要统一

结果:

the precision rate is 97.52 %

在这里插入图片描述


本文链接: http://www.dtmao.cc/news_show_350048.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?