搭建自己的深度学习神经网络

上篇文章,自己推导了一遍误差反向传播算法,从而对深度学习有了一定的认识。这期试着自己搭建一个基于python的深度学习神经网,来解决一定的问题。


需要用到:python3、numpy

数据集:MNIST数据集(一个被”嚼烂”了的数据集, 很多教程都会对它”下手”, 几乎成为一个 “典范”)

MNIST 数据集可在 http://yann.lecun.com/exdb/mnist/ 获取, 它包含了四个部分:

Training set images: train-images-idx3-ubyte.gz (9.9 MB, 解压后 47 MB, 包含 60,000 个样本)

Training set labels: train-labels-idx1-ubyte.gz (29 KB, 解压后 60 KB, 包含 60,000 个标签)

Test set images: t10k-images-idx3-ubyte.gz (1.6 MB, 解压后 7.8 MB, 包含 10,000 个样本)

Test set labels: t10k-labels-idx1-ubyte.gz (5KB, 解压后 10 KB, 包含 10,000 个标签)

MNIST 数据集来自美国国家标准与技术研究所, National Institute of Standards and Technology (NIST). 训练集 (training set) 由来自 250 个不同人手写的数字构成, 其中 50% 是高中学生, 50% 来自人口普查局 (the Census Bureau) 的工作人员. 测试集(test set) 也是同样比例的手写数字数据。

我们创建一个DataParser.py文件来解析MNIST数据:


def load_mnist(path, kind='train'):

labels_path = os.path.join(path, '%s-labels-idx1-ubyte' % kind)

images_path = os.path.join(path, '%s-images-idx3-ubyte' % kind)

with open(labels_path, 'rb')as lbfile:

magic, n = struct.unpack('>II', lbfile.read(8))

labels = np.fromfile(lbfile, dtype=np.uint8)

with open(images_path, 'rb')as imgfile:

magic, num, rows, cols = struct.unpack('>IIII', imgfile.read(16))

images = np.fromfile(imgfile, dtype=np.uint8).reshape(len(labels), 784)

return images /255, labels

除以255把图片像素值映射到[0,1]上。
手写图片的尺寸是28*28


训练思路:
我们将训练过程分为60个epochs,每个epoch里训练1000条数据,训练结束后用测试数据集来计算训练的准确率。
每次测试时,我们需要打乱测试数据,以保证测试结果更准确。
确定网络参数:
由于深度学习需要包括至少2个隐层,所以我们将网络结构定义如下:
数据层——全连接层1——隐层1——全连接层2——隐层2——输出层
数据层、全连接层1各有784个神经元(对应手写图片上的28*28个像素),全连接层2包含256个,输出层10个(对应0—9的概率)
激活函数采用Sigmoid函数,损失函数采用交叉熵损失函数(交叉熵损失函数的导数分母有一个1-x项,尔Sigmoid函数的导数分子有一个1-x项,两者相乘的时候完美解决了使用Sigmoid函数作为激活函数而产生的梯度发散问题)
下面我们就可以用python来实现这个网络了。


数据层定义如下:(数据层正向传播输出其本身,且无需反向传播)

class DataLayer:

    def __init__(self):
        imgs, lbls = dp.load_mnist('', kind='train')
        self.x = imgs
        self.y = lbls
        self.pos = 0

    def forward(self, index):
        pos = index
        xx = self.x[pos]
        ret = (xx.reshape(xx.size,1), self.y[pos])
        return ret

    def backward(self, d):
        pass

测试数据层定义如下:(使用shuffle_data每次打乱数据)

class TestLayer:

    def __init__(self):
        imgs, lbls = dp.load_mnist('', kind='t10k')
        self.x = imgs
        self.y = lbls

    def shuffle_data(self):
        l = len(self.x)
        index = list(range(l))
        np.random.shuffle(index)
        self.x = self.x[index]
        self.y = self.y[index]

    def forward(self, index):
        xx = self.x[index]
        ret = (xx.reshape(xx.size,1), self.y[index])
        return ret

全连接层如下:(权重除以一个值np.sqrt(l_x),会避免产生异常数据)
向前传播forward:矩阵运算,计算z值
反向传播backward:根据接收到的误差更新权重和偏置

class FullConnect:

    def __init__(self, l_x, l_y):
        self.weights = np.random.randn(l_y, l_x) / np.sqrt(l_x)
        self.bias = np.random.randn(l_y, 1)
        self.lr = 0

    def forward(self, x):
        self.x = x
        self.y = np.dot(self.weights, x)+self.bias
        return self.y

    def backward(self, d):
        self.dw = np.dot(d, self.x.T)
        self.db = d
        self.dx = np.dot(self.weights.T, d)

        self.weights -= self.lr * self.dw
        self.bias -= self.lr * self.db

        return self.dx

激活函数:

class Sigmoid:

    def __init__(self):
        pass

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

    def forward(self, x):
        self.x = x
        self.y = self.sigmoid(x)
        return self.y

    def backward(self, d):  
        sig = self.sigmoid(self.x)
        self.dx =d * sig * (1 - sig)
        return self.dx  # 反向传递梯度

损失函数:

class CrossEntropyLoss:
    def __init__(self):
        pass

    def forward(self, x, label):
        self.x = x
        self.label = np.zeros_like(x)
        self.label[label]=1.0

        self.loss=np.nan_to_num(-self.label * np.log(x) -(1- self.label)*np.log(1-x))
        self.loss=np.sum(self.loss) / x.shape[0]
        return  self.loss

    def backward(self):
        self.dx=(self.x-self.label)/self.x /(1- self.x)
        return self.dx

确定准确度的方法为:(数组x中最大值(最大概率)的下标和标记值一样,我们认为结果准确,反之不正确)

class Accuracy:
    def __init__(self):
        pass

    def forward(self, x, label):
        b = x.max()
        if x[label] > b-0.0001:
            return 1
        else:
            return 0

然后我们将这些层进行简单的组装,就可以进行训练了:

def train():
    block_size = 1000
    datalayer1 = DataLayer()
    datalayer2 = TestLayer()

    inner_layers = []
    inner_layers.append(FullConnect(784, 256))
    inner_layers.append(Sigmoid())
    inner_layers.append(FullConnect(256, 10))
    inner_layers.append(Sigmoid())

    lostlayer = CrossEntropyLoss()
    accuracy = Accuracy()
    epochs = 60

    for layer in inner_layers:
        layer.lr = 0.05

    for i in range(epochs):
        print('epochs: ', i)
        losssum = 0
        iters = 0

        for j in range(block_size):
            losssum = 0
            iters += 1
            x, label = datalayer1.forward(i * block_size +j)

            for layer in inner_layers:
                x = layer.forward(x)

            loss = lostlayer.forward(x, label)
            losssum += loss
            d = lostlayer.backward()

            for layer in inner_layers[::-1]:
                d = layer.backward(d)

            if j == block_size-1:
                accu = 0
                datalayer2.shuffle_data()
                for k in range(10000):
                    x, label = datalayer2.forward(index=k)
                    for layer in inner_layers:
                        x = layer.forward(x)
                    accu += accuracy.forward(x, label)
                print('accuracy: ', accu/10000)

我们把学习速度定位0.05,然后经过不到2分钟的训练,就能将准确率提升到96%了。输出数据我们可以看到,第一回合到第二回合性能上有了很大的提升。

epochs:  0
accuracy:  0.6473
epochs:  1
accuracy:  0.846
epochs:  2
accuracy:  0.8799
epochs:  3
accuracy:  0.8828
epochs:  4
accuracy:  0.8964
epochs:  5
accuracy:  0.8988
epochs:  6
accuracy:  0.9022
epochs:  7
accuracy:  0.8958
epochs:  8
accuracy:  0.9058
epochs:  9
accuracy:  0.9157
epochs:  10
accuracy:  0.9055
epochs:  11
accuracy:  0.915
epochs:  12
accuracy:  0.9149
epochs:  13
accuracy:  0.9114
epochs:  14
accuracy:  0.9259
epochs:  15
accuracy:  0.9226
epochs:  16
accuracy:  0.9308
epochs:  17
accuracy:  0.9304
epochs:  18
accuracy:  0.9394
epochs:  19
accuracy:  0.9323
epochs:  20
accuracy:  0.9328
epochs:  21
accuracy:  0.9356
epochs:  22
accuracy:  0.94
epochs:  23
accuracy:  0.9456
epochs:  24
accuracy:  0.9431
epochs:  25
accuracy:  0.9374
epochs:  26
accuracy:  0.9466
epochs:  27
accuracy:  0.9468
epochs:  28
accuracy:  0.9465
epochs:  29
accuracy:  0.9389
epochs:  30
accuracy:  0.9471
epochs:  31
accuracy:  0.9473
epochs:  32
accuracy:  0.9524
epochs:  33
accuracy:  0.953
epochs:  34
accuracy:  0.9501
epochs:  35
accuracy:  0.944
epochs:  36
accuracy:  0.9458
epochs:  37
accuracy:  0.9554
epochs:  38
accuracy:  0.9556
epochs:  39
accuracy:  0.9536
epochs:  40
accuracy:  0.9497
epochs:  41
accuracy:  0.9557
epochs:  42
accuracy:  0.9548
epochs:  43
accuracy:  0.9517
epochs:  44
accuracy:  0.9496
epochs:  45
accuracy:  0.9495
epochs:  46
accuracy:  0.9579
epochs:  47
accuracy:  0.9573
epochs:  48
accuracy:  0.9485
epochs:  49
accuracy:  0.9605
epochs:  50
accuracy:  0.9618
epochs:  51
accuracy:  0.9625
epochs:  52
accuracy:  0.9599
epochs:  53
accuracy:  0.9574
epochs:  54
accuracy:  0.961
epochs:  55
accuracy:  0.9621
epochs:  56
accuracy:  0.9597
epochs:  57
accuracy:  0.9565
epochs:  58
accuracy:  0.9591
epochs:  59
accuracy:  0.9604

到此,通过搜集网上各种资料,自己实现了第一个深度学习神经网络,中间不免有不合理的地方,继续加油!!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容