《深度学习实战笔记》-三、神经网络

学习内容:

①BP神经网络;

②全连接神经网络(DNN);

③sklearn框架;

④精度P、召回率R、准确度F1

神经网络推导过程

《深度学习实战笔记》-三、神经网络_第1张图片《深度学习实战笔记》-三、神经网络_第2张图片

代码实现-手写字识别

import numpy as np
# load_digits 为sklearn自带数据集的手写字数据库
from sklearn.datasets import load_digits
# LabelBinarizer 为sklearn自带的预处理部分-表示二值化处理正例0;负例1
from sklearn.preprocessing import LabelBinarizer
# train_test_split是sklearn中模型选择用于划分数据集,即将原始数据集划分成测试集和训练集两部分的函数。
from sklearn.model_selection import train_test_split
# classification_report是sklearn检验机器学习模型效果的定量指标的模型分类评估
from sklearn.metrics import classification_report

import matplotlib.pyplot as plt

# 载入数据
digits = load_digits()
# 显示图片,在此数据集是一个1797 * 8 * 8 的三维矩阵,即有1797 张 8 * 8 的数字图片组成
# 三维数组,x.shape[0]代表包含二维数组的个数,x.shape[1]表示二维数组的行数,x.shape[2]表示二维数组的列数。
# min(digits.images.shape[0], 3)最终在所有的图片中选择了三张图片作为展示,以防展示图片个数大于数据集中图片个数
for i in range(min(digits.images.shape[0], 3)):
    # 利用matplotlib包对图片进行绘制,绘制成功后,返回一个matplotlib类型的数据,cmap选择色度为黑白
    plt.imshow(digits.images[i], cmap='gray')
    plt.show()

# 数据
X = digits.data
# 标签(数据集本身已经提供)
y = digits.target

# 定义一个神经网络,结构,64-100-10
# 定义输入层到隐藏层之间的权值矩阵
# np.random.random((64, 100))为生成64行100列的0-1之间的浮点数
V = np.random.random((64, 100)) * 2 - 1
# 定义隐藏层到输出层之间的权值矩阵生成100行10列的0-1之间的浮点数
W = np.random.random((100, 10)) * 2 - 1

# 数据切分
# 1/4为测试集,3/4为训练集,train_test_split(X, y,test_size )test_size 默认是0.75
X_train, X_test, y_train, y_test = train_test_split(X, y)

# 标签二值化
# fit_transform()函数:直接根据label本身有多少类,然后使用独热编码,把label二进制化。
# 0 -> 1000000000
# 3 -> 0001000000
# 9 -> 0000000001
labels_train = LabelBinarizer().fit_transform(y_train)


# 激活函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))


# 激活函数的导数
def dsigmoid(x):
    return x * (1 - x)


#  训练模型此训练模型不包含偏执b
def train(X, y, steps=10000, lr=0.011):
    # 返回全局变量的字典。
    global V, W
    for n in range(steps + 1):
        # 随机选取一个数据
        i = np.random.randint(X.shape[0])
        # 获取一个数据,将输入视为至少转换为二维的数组。
        x = X[i]
        x = np.atleast_2d(x)
        # BP算法公式
        # 计算隐藏层的输出,np.dot()-矩阵乘法 v为输入层到隐含层的初始权重
        L1 = sigmoid(np.dot(x, V))
        # 计算输出层的输出 隐含层到输出层的初始权重
        L2 = sigmoid(np.dot(L1, W))
        # 计算L2_delta--损失函数对预测值求导 预测值对于L2求导
        # L1_delta
        L2_delta = (y[i] - L2) * dsigmoid(L2)
        # x.dot(y) 等价于 np.dot(x,y) ———x是m × n 矩阵 ,y是n×m矩阵,则x.dot(y) 得到m×m矩阵。
        # 求v需要更新的权重值
        L1_delta = L2_delta.dot(W.T) * dsigmoid(L1)
        # 更新权值 lr为学习率
        W += lr * L1.T.dot(L2_delta)
        V += lr * x.T.dot(L1_delta)

        # 每训练1000次预测一次准确率
        if n % 1000 == 0:
            # 训练后返回预测结果,是标签值。
            output = predict(X_test)
            # numpy.argmax(array, axis) 用于返回一个numpy数组中最大值的索引值(下标位置)。当一组中同时出现几个最大值时,返回第一个最大值的索引值。
            # axis可以从左至右计算数组的方括号数目,一个方括号是一维数组,两个方括号是二维数组,三个方括号是三维数组。
            predictions = np.argmax(output, axis=1)
            # mean()函数功能:求取均值
            # 经常操作的参数为axis,以m * n矩阵举例:
            # axis 不设置值,对 m * n个数求均值,返回一个实数
            # axis = 0:压缩行,对各列求均值,返回 1 * n矩阵
            # axis = 1 :压缩列,对各行求均值,返回m * 1矩阵
            acc = np.mean(np.equal(predictions, y_test))
            dW = L1.T.dot(L2_delta)
            dV = x.T.dot(L1_delta)
            # np.square()矩阵平方,np.sqrt()按元素确定数组的正平方根
            gradient = np.sum([np.sqrt(np.sum(np.square(j))) for j in [dW, dV]])
            print('steps(步长)', n, 'accuracy(准确率)', acc, 'gradient(斜率)', gradient)
            # print(classification_report(predictions,y_test))


def predict(x):
    # 计算隐藏层的输出
    L1 = sigmoid(np.dot(x, V))
    # 计算输出层的输出
    L2 = sigmoid(np.dot(L1, W))
    return L2


# 开始训练
# train(X_train, labels_train, 20000, lr=0.11)
train(X_train, labels_train, 20000, lr=0.011)
# 训练后结果对比
output = predict(X_test)
predictions = np.argmax(output, axis=1)
acc = np.mean(np.equal(predictions, y_test))
print('accuracy(准确率)', acc)
# 目标值,估计值,digits:int,输出浮点值的位数
print(classification_report(predictions, y_test, digits=4))

你可能感兴趣的:(深度学习实战-自学笔记,神经网络,深度学习,sklearn)