深度学习与计算机视觉:基于Python的神经网络的实现

在前面两篇文章介绍了深度学习的一些基本概念,本文则使用Python实现一个简单的深度神经网络,并使用MNIST数据库进行测试。
神经网络的实现,包括以下内容:

  • 神经网络权值的初始化
  • 正向传播
  • 误差评估
  • 反向传播
  • 更新权值

主要是根据反向传播的4个基本方程,利用Python实现神经网络的反向传播。

初始化

首先定义代表神经网络的类NeuralNetwork,

class NeuralNetwork:
    def __init__(self,layers,alpha=0.1):
        self.W = []
        self.layers = layers
        self.alpha = alpha

有三个属性,

  • W存储各个层之间的权值矩阵,也是神经网络要更新学习的
  • layers 神经网络的结构,例如: [2,2,1]表示输入层有2个神经元,隐藏层2个神经元,输出层只有1个神经元。
  • alpha 学习速率

接下来初始化各个层之间的权值矩阵

for i in np.arange(0,len(layers) - 2):
    w = np.random.randn(layers[i] + 1,layers[i + 1] + 1)
    self.W.append(w / np.sqrt(layers[i]))

注意上面生成权值矩阵的大小layers[i] + 1,layers[i + 1] + 1,都加了1。 这是将神经元的偏置和权值统一的放到了权值矩阵里面。
\[ \left[ \begin{array}{c}w_{11} & w_{12} \\ w_{21} & w_{22}\end{array} \right] \cdot \left[\begin{array}{c}x_1 \\ x_2\end{array}\right] + \left[\begin{array}{c}b_1 \\ b_2\end{array}\right] = \left[\begin{array}{c}w_{11}x_1 + w{12}x_2 + b_1 \\ w_{21}x_1 + w_{22}x_2 + b_2 \end{array}\right] \]

可以将上式写成齐次的形式
\[ \left[ \begin{array}{c}w_{11} & w_{12} & b_1 \\ w_{21} & w_{22} &b_2 \end{array} \right] \cdot \left[\begin{array}{c}x_1 \\ x_2 \\ 1\end{array}\right] \]

使用统一的矩阵运算,在正向反向传播的时候更方便。

在输出层的神经元并没有偏置,所以要单独初始化输出层的权值矩阵

        w = np.random.randn(layers[-2] + 1,layers[-1])
        self.W.append(w / np.sqrt(layers[-2]))

下面实现Python的magic function __repr__输出神经网络结构

    def __repr__(self):
        return "NeuralNetWork:{}".format("-".join(str(l) for l in self.layers))

激活函数

在神经网络中使用sigmoid作为激活函数,实现sigmoid及其导数

    def sigmoid(self,x):
        return 1.0 / (1 + np.exp(-x))

    def sigmoid_deriv(self,x):
        return x * (1 - x)

正向反向传播

这一部分是神经的网络的核心了。下面实现fit方法,在方法中完成神经网络权值更新(训练)的过程。

    def fit(self,X,y,epochs=1000,displayUpdate=100):
        X = np.c_[X,np.ones((X.shape[0]))]

        for epoch in np.arange(0,epochs):
            for(x,target) in zip(X,y):
                self.fit_partial(x,target)

            # check to see if we should display a training update
            if epoch == 0 or (epoch + 1) % displayUpdate == 0:
                loss = self.calculate_loss(X,y)
                print("[INFO] epoch={},loss={:.7f}".format(epoch + 1,loss))

该函数有4个参数:

  • X是输入的样本数据
  • y是样本的真是值
  • epochs训练的轮数
  • displayUpdate 输出训练的loss值。

X = np.c_[X,np.ones((X.shape[0]))]将输入训练的样本表示为齐次向量(也就是在末尾添1)。fit_partial是对输入的每个样本进行训练,包括正向传播,反向传播以及权值的更新。

    def fit_partial(self,x,y):
        A = [np.atleast_2d(x)]
        # 正向传播
        # 层层之间的数据传递
        for layer in np.arange(0,len(self.W)):
        
            # 输入经过加权以及偏置后的值
            net = A[layer].dot(self.W[layer])

            # 神经元的输出
            out = self.sigmoid(net)

            # 保存下来,反向传播的时候使用
            A.append(out)

上面完成了神经玩过的正向传播过程,下面根据反向传播的4个基本方程进行反向传播。
首先根据\(BP1\),
\[ \delta^L = \frac{\partial e}{\partial a^L} \odot \sigma'(z^L) \tag{BP1} \]
计算输出层的误差\(\delta^L\)

        error = A[-1] - y # 输出层的误差,均值方差作为损失函数

        D = [error * self.sigmoid_deriv(A[-1])]

得到输出层的误差D后,根据\(BP2\)计算各个层的误差
\[ \delta^{L-1} = (W^L)^T\delta^L \odot \sigma'(z^{L-1}) \tag{BP2} \]

        for layer in np.arange(len(A) - 2,0 ,-1):
            delta = D[-1].dot(self.W[layer].T)
            delta = delta * self.sigmoid_deriv(A[layer])
            D.append(delta)
        D = D[::-1]

D反转,和各个层的索引对应起来,下面根据\(BP3,BP4\)计算权值矩阵和偏置的导数
\[ \frac{\partial e}{b_j^l} = \delta_j^l \tag{BP3} \]
\[ \frac{\partial e}{w_{jk}^l} = \delta_j^l a_k^{l-1} \tag{BP4} \]

        for layer in np.arange(0,len(self.W)):
            self.W[layer] += -self.alpha * A[layer].T.dot(D[layer])

首先求得权值和偏置的导数(权值和偏置统一到同一个矩阵中)A[layer].T.dot(D[layer],然后将梯度乘以学习速率alpha 每次权值减小的步长。

上述就完成利用反向传播算法更新权值的过程。 关于反向传播四个基本方程的推导过程,可以参考文章深度学习与计算机视觉: 搞懂反向传播算法的四个基本方程

误差评估

上面代码已经实现了深度学习的训练过程,下面实现predict输出使用训练好的模型预测的结果,calculate_loss评估训练后模型的评估

    def predict(self,X,addBias=True):
        p = np.atleast_2d(X)

        if addBias:
            p = np.c_[p,np.ones((p.shape[0]))]

        for layer in np.arange(0,len(self.W)):
                p = self.sigmoid(np.dot(p,self.W[layer]))

        return p 
    def calculate_loss(self,X,targets):

        targets = np.atleast_2d(targets)
        predictions = self.predict(X,addBias=False)
        loss = 0.5 * np.sum((predictions - targets) ** 2)

        return loss 

MNIST分类识别

使用上面实现的深度神经网络对MNIST手写体进行识别,首先导入必要的包

import NeuralNetwork
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn import datasets

需要使用sklearn包中的一些工具,进行数据的处理。

# load MNIST数据集,并使用min/max对数据进行归一化
digits = datasets.load_digits()
data = digits.data.astype("float")
data = (data - data.min()) / (data.max() - data.min())

print("[INFO] samples: {}, dim: {}".format(data.shape[0], data.shape[1]))

将数据拆分为训练集和测试集,并对MNIST的类别进行编码

(trainX, testX, trainY, testY) = train_test_split(data, digits.target, test_size=0.25)

# convert the labels from integers to vectors
trainY = LabelBinarizer().fit_transform(trainY)
testY = LabelBinarizer().fit_transform(testY)

下面构建神经网络结构,并使用训练集进行训练

nn = NeuralNetwork([data.shape[1], 32,16, 10])

print ("[INFO] {}".format(nn))

nn.fit(trainX, trainY, epochs=1000)

神经网络结构为:64-32-16-10,其中64为输入数据的大小,10输出类别的个数。

最后评估训练得到的模型

predictions = nn.predict(testX)

print(classification_report(testY.argmax(axis=1), predictions.argmax(axis=1)))

最终的输出结果:

[INFO] loading MNIST (sample) dataset...
[INFO] samples: 1797, dim: 64
[INFO] training network...
[INFO] NeuralNetWork:64-32-16-10
[INFO] epoch=1,loss=607.1711647
[INFO] epoch=100,loss=7.1082795
[INFO] epoch=200,loss=4.0731690
[INFO] epoch=300,loss=3.1401868
[INFO] epoch=400,loss=2.8801101
[INFO] epoch=500,loss=1.8738122
[INFO] epoch=600,loss=1.7461474
[INFO] epoch=700,loss=1.6624043
[INFO] epoch=800,loss=1.1852884
[INFO] epoch=900,loss=0.6710255
[INFO] epoch=1000,loss=0.6336826
[INFO] evaluating network...
              precision    recall  f1-score   support

           0       1.00      0.95      0.97        39
           1       0.84      1.00      0.92        38
           2       1.00      0.98      0.99        41
           3       0.93      0.98      0.95        52
           4       0.91      0.97      0.94        40
           5       0.98      0.98      0.98        41
           6       1.00      0.96      0.98        51
           7       1.00      0.98      0.99        48
           8       0.98      0.89      0.93        55
           9       0.98      0.93      0.95        45

   micro avg       0.96      0.96      0.96       450
   macro avg       0.96      0.96      0.96       450
weighted avg       0.96      0.96      0.96       450

如上测试结果,在测试集的上表现还算不错。

总结

本文使用Python简单的实现了一个神经网络。 主要是利用反向传播的4个基本方程,实现反向传播算法,更新各个神经元的权值。 最后使用该网络,对MNIST数据进行识别分类。

上面实现的神经网络只是“玩具”,用以加深对深度学习的训练过程以及反向传播算法的理解。后面将使用Keras和PyTorch来构建神经网络。

本文代码在git库 https://github.com/brookicv/machineLearningSample

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
采用深度学习方法的Python计算机视觉,第二卷 本书循序渐进共分为3卷, 第一卷为深度学习入门,第二卷为高级技术最佳实践,第三卷结合ImageNet大规模神经网络训练 Since this book covers a huge amount of content, I’ve decided to break the book down into three volumes called “bundles”. A bundle includes the eBook, video tutorials, and source code for a given volume. Each bundle builds on top of the others and includes all content from the lower volumes. You should choose a bundle based on: (1) how in-depth you want to study deep learning, computer vision, and visual recognition and (2) your particular budget. You can find a quick breakdown of the three bundles below — the full list of topics to be covered can be found later on this page: Starter Bundle: A great fit for those taking their first steps towards deep learning for image classification mastery. You’ll learn the basics of (1) machine learning, (2) neural networks, (3) Convolutional Neural Networks, and (4) how to work with your own custom datasets. Practitioner Bundle: Perfect for readers who are ready to study deep learning in-depth, understand advanced techniques, and discover common best practices and rules of thumb. ImageNet Bundle: The complete deep learning for computer vision experience. In this bundle, I demonstrate how to train large-scale neural networks on the massive ImageNet dataset. You just can’t beat this bundle if you want to master deep learning for computer vision.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值