欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

吴恩达机器学习作业3:Multi-class Classification and Neural Networks python实现

程序员文章站 2022-03-10 19:55:02
1.数据可视化#加载数据path1 = r'C:\Users\郑思铭\Desktop\py\hw_3\ex3data1.mat'data1 = scio.loadmat(path1)x = data1['X']y = data1['y']#数据可视化m = x.shape[0]random = np.random.permutation(range(m))temp = random[0:100]select = x[temp, :]displaydata(select)数据可视化...

一 、 多分类器

1.数据可视化

#加载数据
path1 = r'C:\Users\郑思铭\Desktop\py\hw_3\ex3data1.mat'
data1 = scio.loadmat(path1)
x = data1['X']
y = data1['y']

#数据可视化
m = x.shape[0]
random = np.random.permutation(range(m))
temp = random[0:100]
select = x[temp, :]
displaydata(select)

数据可视化的难点是将x矩阵的每个example(1 * 200)恢复成 (20 *20)的格式,然后以 (20 *20)的格式嵌入每个显示图片的小格子中,一共显示100个example,小格子结构为( 10 *10)。

然而在实现的过程中一直有个转置的点无法理解:

import matplotlib.pyplot as plt
import numpy as np

def displaydata(x):

    #计算每个example的尺寸
    m, n = x.shape
    height = np.sqrt(n).astype(int)
    width = (n / height).astype(int)

    #计算display example的行个数、列个数
    rows = np.sqrt(m).astype(int)
    cols = (m / rows).astype(int)

    #设置example之间的间隙大小
    pad = 1

    #初始化display图像的矩阵

    dis_mat = np.zeros((pad + rows*(pad + width), pad + cols*(pad + height)))

    #将x的每一行信息输入example矩阵中

    for i in range(rows):

        for j in range(cols):
            max_val = x[i*10 + j, :].max()
            temp = x[i*10 + j, :].reshape(width, height) / max_val

#无法理解这里为什么不用转置!!!!!!!!!!!!!!!
            dis_mat[pad + i*(pad + height) + np.arange(height), pad + j*(pad + width) + np.arange(width)[:, np.newaxis]] = \
            temp.reshape(width, height)


    plt.figure()
    plt.imshow(dis_mat, cmap='gray', extent=[-1, 1, -1, 1])
    plt.axis('off')
    plt.title('Random Seleted Digits')
    plt.show()

代码中:

dis_mat[pad + i*(pad + height) + np.arange(height), pad + j*(pad + width) + np.arange(width)[:, np.newaxis]] = \
            temp.reshape(width, height)

这样选取的位置矩阵应该为:
[(0,) (1,) (2,) (3,)…(19,)]
[(0,) (1,) (2,) (3,)…(19,)]

[(0,) (1,) (2,) (3,)…(19,)] (行坐标)

[(,0) (,1) (,2) (,3)…(,19)]
[(,0) (,1) (,2) (,3)…(,19)]

[(,0) (,1) (,2) (,3)…(,19)]
(列坐标)

组合成的位置矩阵:

[ (0,0) (1,0) (2,0)…(19,0)]
[ (0,1) (1,1) (2,1)…(19,1)]
[ (0,2) (1,2) (2,2)…(19,2)]

[(0,19) (1,19) (2,19)…(19,19)]

reshape过结构为(20*20)的example按位置矩阵的坐标对应入座。然而位置矩阵是正常矩阵的转置形式,比如example的第一行第二点像素(0,1)在位置矩阵相同位置找到的坐标是(1,0),所以会去第二行的第一点组成图像。这么一来,所有的example形成的图像也是转置过的!

然而问题来了,每个数字并没有转置:

吴恩达机器学习作业3:Multi-class Classification and Neural Networks python实现
原因是matlab的reshape和python的reshape是不一样的。
matlab的reshape的按列排序,而python的reshape的按行排列!!!!

因此mat格式的每个example(1 * 400)并不是在(20 * 20)的图像依次取一行拼成一行400个点,而是取一列20点依次拼接成400点!

2.代价函数、梯度下降

代价函数

import numpy as np
from Sigmod import sigmod


def costfunction(theta, x, y, mylambda):

    m = x.shape[0]
    hx = sigmod(np.dot(x, theta))
    y = y.flatten()
    temp1 = np.multiply(y, np.log(hx))
    temp2 = np.multiply(1-y, np.log(1-hx))
    temp3 = mylambda / (2 * m) * np.sum(np.power(theta[1:], 2))
    cost = -np.mean(temp1 + temp2) + temp3

    return cost

梯度下降:

import numpy as np
from Sigmod import sigmod


def gradinet(theta, x, y, mylambda):

    m = x.shape[0]
    hx = sigmod(np.dot(x, theta))
    y = y.flatten()

    grad = np.dot(x.T, hx - y)/m
    temp = mylambda/m * np.array(theta[1:])
    grad[1:] = grad[1:] + temp
    return grad

梯度下降注意返回值是一维数组,否则在优化函数传入时会报错

3.分类器的构建

其实就是求10个theta ,每个theta用来计算某个example的是某个数字的概率有多大。
比如,我拿到一个example,用这个example的特征和theta0、theta1…theta9 进行计算,然后得到10个概率,选取概率最大的那个对应分类作为识别的结果。

def onevsall(theta, x, y, num_class, mylambda):

    m = num_class
    n = x.shape[1]
    theta_mat = np.zeros([m, n])

    for i in range(m):
        if i == 0:
            y_this_class = np.where(y == 10, 1, 0)
        else:
            y_this_class = np.where(y == i, 1, 0)

        theta_temp = opt.minimize(fun=costfunction, x0=theta,
                                  args=(x, y_this_class, mylambda), method='TNC', jac=gradinet).x
        theta_mat[i, :] = theta_temp

    return theta_mat

4.预测模块

对每个example进行识别,计算准确率

import numpy as np
from Sigmod import sigmod


def prediction(theta, x, y):
    pred_mat = sigmod(np.dot(x, theta.T))
    m, n = pred_mat.shape

    pred = np.zeros(m)

    for i in range(m):
        pred[i] = 0
        flag = -1
        for j in range(n):

            if pred_mat[i, j] > flag:
                pred[i] = j
                flag = pred_mat[i, j]

        if pred[i] == 0:
            pred[i] = 10

    pred = np.array(pred).reshape([m, 1])
    temp = np.where(y == pred, 1, 0)
    corret = np.mean(temp)

    return corret

theta_train = onevsall(initial_theta, x, y, num_class, lambda_test)
corret = prediction(theta_train, x, y)
print(corret)

结果:96.46 % 的准确率
吴恩达机器学习作业3:Multi-class Classification and Neural Networks python实现

二、神经网络

1.前向传递、准确率预测

在练习中,已经给出神经网络的参数Theta1、Theta2,只需要利用这两个权重矩阵计算 hx 即可。

前向传递:

import numpy as np
from Sigmod import sigmod


def prediction_nn(theta1, theta2, x, y):

    m, n = x.shape
    pred = np.zeros(m)

#第二层神经网络的激活因子
    z2 = np.dot(theta1, x.T)
    a2 = sigmod(z2)
    one = np.ones([1, m])
    a2 = np.vstack([one, a2])

#第三层神经网络的激活因子
    z3 = np.dot(theta2, a2)
    hx = sigmod(z3).T

#接下

准确率预测

num_class = hx.shape[1]
    for i in range(m):
        pred[i] = 0
        flag = -1
        for j in range(num_class):

            if hx[i, j] > flag:
                pred[i] = j + 1
                flag = hx[i, j]

    pred = np.array(pred).reshape([m, 1])
    temp = np.where(y == pred, 1, 0)
    corret = np.mean(temp)

    return corret

结果:
吴恩达机器学习作业3:Multi-class Classification and Neural Networks python实现

本文地址:https://blog.csdn.net/zsiming/article/details/107633623