数据科学家程序猿的自我修养程序员

对比学习用 Keras 搭建 CNN RNN 等常用神经网络

2016-11-23  本文已影响31439人  不会停的蜗牛

参考:
各模型完整代码
周莫烦的教学网站
这个网站上有很多机器学习相关的教学视频,推荐上去学习学习。

Keras 是一个兼容 Theano 和 Tensorflow 的神经网络高级包, 用他来组件一个神经网络更加快速, 几条语句就搞定了. 而且广泛的兼容性能使 Keras 在 Windows 和 MacOS 或者 Linux 上运行无阻碍.

今天来对比学习一下用 Keras 搭建下面几个常用神经网络:

  1. 回归
  2. RNN回归
  3. 分类
  4. CNN分类
  5. RNN分类
  6. 自编码分类

它们的步骤差不多是一样的:

  1. [导入模块并创建数据]
  2. [建立模型]
  3. [定义优化器]
  4. [激活模型]
  5. [训练模型]
  6. [检验模型]
  7. [可视化结果]

为了对比学习,用到的数据也差不多是一样的,
所以本文只把注意力放在 2. [建立模型] 上面,其它步骤大同小异,可以去参考里提到的教学网站观看或者直接看源代码。


1. 回归

目的是对一组数据进行拟合。

1. 用 Sequential 建立 model
2. 再用 model.add 添加神经层,添加的是 Dense 全连接神经层。

参数有两个,一个是输入数据和输出数据的维度,本代码的例子中 x 和 y 是一维的。

如果需要添加下一个神经层的时候,不用再定义输入的纬度,因为它默认就把前一层的输出作为当前层的输入。在这个例子里,只需要一层就够了。

# build a neural network from the 1st layer to the last layer
model = Sequential()
model.add(Dense(output_dim=1, input_dim=1))

2. RNN回归

我们要用 sin 函数预测 cos 数据,会用到 LSTM 这个网络。

RNN vs LSTM

1. 搭建模型,仍然用 Sequential。
2. 然后加入 LSTM 神经层。

3. 有个不同点是 TimeDistributed。

在上一个回归问题中,我们是直接加 Dense 层,因为只在最后一个输出层把它变成一个全连接层。
今天这个问题是每个时间点都有一个 output,那需要 dense 对每一个 output 都进行一次全连接的计算。

model = Sequential()
# build a LSTM RNN
model.add(LSTM(
    batch_input_shape=(BATCH_SIZE, TIME_STEPS, INPUT_SIZE),       # Or: input_dim=INPUT_SIZE, input_length=TIME_STEPS,
    output_dim=CELL_SIZE,
    return_sequences=True,      # True: output at all steps. False: output as last step.
    stateful=True,              # True: the final state of batch1 is feed into the initial state of batch2
))
# add output layer
model.add(TimeDistributed(Dense(OUTPUT_SIZE)))
adam = Adam(LR)
model.compile(optimizer=adam,
              loss='mse',)

3. 分类

数据用的是 Keras 自带 MNIST 这个数据包,再分成训练集和测试集。x 是一张张图片,y 是每张图片对应的标签,即它是哪个数字。

简单介绍一下相关模块:

import numpy as np
np.random.seed(1337)  # for reproducibility
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.optimizers import RMSprop

在回归网络中用到的是 model.add 一层一层添加神经层,今天的方法是直接在模型的里面加多个神经层。好比一个水管,一段一段的,数据是从上面一段掉到下面一段,再掉到下面一段。

# Another way to build your neural net
model = Sequential([
    Dense(32, input_dim=784),
    Activation('relu'),
    Dense(10),
    Activation('softmax'),
])

4. CNN分类

CNN

数据仍然是用 mnist。

1. 建立网络第一层,建立一个 Convolution2D,参数有 filter 的数量。

# Another way to build your CNN
model = Sequential()

# Conv layer 1 output shape (32, 28, 28)
model.add(Convolution2D(
    nb_filter=32,
    nb_row=5,
    nb_col=5,
    border_mode='same',     # Padding method
    dim_ordering='th',      # if use tensorflow, to set the input dimension order to theano ("th") style, but you can change it.
    input_shape=(1,         # channels
                 28, 28,)    # height & width
))
model.add(Activation('relu'))

2. Pooling 是一个向下取样的过程.
它可以缩小生成出来的长和宽,高度不需要被压缩。

# Pooling layer 1 (max pooling) output shape (32, 14, 14)
model.add(MaxPooling2D(
    pool_size=(2, 2),
    strides=(2, 2),
    border_mode='same',    # Padding method
))

3. 接下来建立第二个神经层

# Conv layer 2 output shape (64, 14, 14)
model.add(Convolution2D(64, 5, 5, border_mode='same'))
model.add(Activation('relu'))

# Pooling layer 2 (max pooling) output shape (64, 7, 7)
model.add(MaxPooling2D(pool_size=(2, 2), border_mode='same'))

4. 接下来进入全联接层

# Fully connected layer 1 input shape (64 * 7 * 7) = (3136), output shape (1024)
model.add(Flatten())
model.add(Dense(1024))
model.add(Activation('relu'))

5. 在第二个全连接层,输出 10 个 unit, 用 softmax 作为分类。

# Fully connected layer 2 to shape (10) for 10 classes
model.add(Dense(10))
model.add(Activation('softmax'))

5. RNN分类

RNN分类

RNN 是一个序列化的神经网,我们处理图片数据的时候,也要以序列化的方式去考虑。
图片是由一行一行的像素组成,我们就一行一行地去序列化地读取数据。最后再进行一个总结,来决定它到底是被分辨成哪一类。

用到的参数含义:

1. 用 Sequential 建立模型,就是一层一层地加上神经层。

# build RNN model
model = Sequential()

2. 加上 SimpleRNN。
batch_input_shape 就是在后面处理批量的训练数据时它的大小是多少,有多少个时间点,每个时间点有多少个像素。

# RNN cell
model.add(SimpleRNN(
    # for batch_input_shape, if using tensorflow as the backend, we have to put None for the batch_size.
    # Otherwise, model.evaluate() will get error.
    batch_input_shape=(None, TIME_STEPS, INPUT_SIZE),       # Or: input_dim=INPUT_SIZE, input_length=TIME_STEPS,
    output_dim=CELL_SIZE,
    unroll=True,
))

3. 加 Dense 输出层。
输出 output 长度为 10,接着用 softmax 激活函数用于分类。

# output layer
model.add(Dense(OUTPUT_SIZE))
model.add(Activation('softmax'))

4. 在训练的时候有一个小技巧,就是怎么去处理批量。
输出结果时每 500 步输出一下测试集的准确率和损失。

需要用到 BATCH_INDEX,一批批地截取数据,下一批的时候,这个 BATCH_INDEX 就需要累加,后面的时间点和步长没有变化都是28。
y 的批量和 x 的处理是一样的,只不过 y 只有二维,所以它只有两个参数。

后面有一个判断语句,如果这个 index 大于训练数据的总数,index 就变为 0,再从头开始一批批处理。

# training
for step in range(4001):
    # data shape = (batch_num, steps, inputs/outputs)
    X_batch = X_train[BATCH_INDEX: BATCH_INDEX+BATCH_SIZE, :, :]
    Y_batch = y_train[BATCH_INDEX: BATCH_INDEX+BATCH_SIZE, :]
    cost = model.train_on_batch(X_batch, Y_batch)
    BATCH_INDEX += BATCH_SIZE
    BATCH_INDEX = 0 if BATCH_INDEX >= X_train.shape[0] else BATCH_INDEX

    if step % 500 == 0:
        cost, accuracy = model.evaluate(X_test, y_test, batch_size=y_test.shape[0], verbose=False)
        print('test cost: ', cost, 'test accuracy: ', accuracy)

6. 自编码分类

自编码

自编码,简单来说就是把输入数据进行一个压缩和解压缩的过程。
原来有很多 Feature,压缩成几个来代表原来的数据,解压之后恢复成原来的维度,再和原数据进行比较。

做的事情是把 datasets.mnist 数据的 28×28=784 维的数据,压缩成 2 维的数据,然后在一个二维空间中可视化出分类的效果。

模型结构:

encoding_dim,要压缩成的维度。

# in order to plot in a 2D figure
encoding_dim = 2

# this is our input placeholder
input_img = Input(shape=(784,))

建立 encoded 层和 decoded 层,再用 autoencoder 把二者组建在一起。训练时用 autoencoder 层。

1. encoded 用4层 Dense 全联接层
激活函数用 relu,输入的维度就是前一步定义的 input_img
接下来定义下一层,它的输出维度是64,输入是上一层的输出结果。
在最后一层,我们定义它的输出维度就是想要的 encoding_dim=2

2. 解压的环节,它的过程和压缩的过程是正好相反的。
相对应层的激活函数也是一样的,不过在解压的最后一层用到的激活函数是 tanh。因为输入值是由 -0.5 到 0.5 这个范围,在最后一层用这个激活函数的时候,它的输出是 -1 到 1,可以是作为一个很好的对应。

# encoder layers
encoded = Dense(128, activation='relu')(input_img)
encoded = Dense(64, activation='relu')(encoded)
encoded = Dense(10, activation='relu')(encoded)
encoder_output = Dense(encoding_dim)(encoded)

# decoder layers
decoded = Dense(10, activation='relu')(encoder_output)
decoded = Dense(64, activation='relu')(decoded)
decoded = Dense(128, activation='relu')(decoded)
decoded = Dense(784, activation='tanh')(decoded)

# construct the autoencoder model
autoencoder = Model(input=input_img, output=decoded)

接下来直接用 Model 这个模块来组建模型
输入就是图片,输出是解压的最后的结果。

# construct the encoder model for plotting
encoder = Model(input=input_img, output=encoder_output)

当我们想要看由 784 压缩到 2维后,这个结果是什么样的时候,也可以只单独组建压缩的板块,此时它的输入是图片,输出是压缩环节的最后结果。

最后分类的可视化结果:



历史技术博文链接汇总

我是 不会停的蜗牛 Alice
85后全职主妇
喜欢人工智能,行动派
创造力,思考力,学习力提升修炼进行中
欢迎您的喜欢,关注和评论!

上一篇下一篇

猜你喜欢

热点阅读