美文网首页
keras CNN入门(一)

keras CNN入门(一)

作者: YvanYan | 来源:发表于2020-08-21 21:35 被阅读0次

    本文为吴恩达教授的Tensorflow实践系列课程的学习记录。


    完整代码:https://github.com/YvanYan/keras/tree/master/part1-cnn

    关于tensorflow的安装,网上有许多博客讲解的十分详细,本文不再叙述。

    本文内容:
    1.搭建一个简单的神经网络
    2.实现简单的卷积神经网络
    3.使用卷积神经网络处理真实图片

    1.搭建一个简单的神经网络

    首先加载数据集,由于国内网络环境问题,因此是通过数据集链接将数据下载到本地,再进行加载。本地数据集是IDX文件格式,因此可以通过项目中loaddata.py文件进行读取。

    mnist = tf.keras.datasets.fashion_mnist
    (train_imgs, train_labels), (test_imgs, test_labels) = mnist.load_data()
    

    对数据进行归一化,因为每个像素值是0-255,所以将像素值归一化成0-1。归一化使网络更好的收敛,准确率更高。

    training_images  = training_images / 255.0
    test_images = test_images / 255.0
    

    搭建训练模型。Flatten表示将二维数据变成1维,图像数据是 28* 28,通过Flatten层后就变成了 784* 1。Dense表示神经网络中的层,每一层需要指定神经元的数量激活函数神经元的数量在一定程度上可以提高准确性,但会花费更多的时间。对于简单的数据集,增加神经元的数量并不能很明显的提高准确率。激活函数可以非线性的改变上一层的输出结果,从而更好的拟合各种函数。各种常用的激活函数模型可以参考这篇博客。最后一层输出层的神经元数量为10,因为在这个数据集中,图像是十分类问题,所有需要最后有十个不同的神经元对应不同的类别。如果最后输出层的神经元数量少于分类数,会报错。

    model = tf.keras.models.Sequential([tf.keras.layers.Flatten(), 
                                        tf.keras.layers.Dense(128, activation=tf.nn.relu), 
                                        tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
    

    编译、训练和评估模型。compile来编译网络,需要指明优化器和损失函数。fit来训练网络,传入训练图像、训练图像标签、训练轮次。轮次越多准确率越高,耗时越多,但简单的问题轮次越多并不表示越好,因为网络可能会过拟合,即在训练集表现极好,但对于测试集表现一般,这样的结果表示网络的泛化能力较差。evaluate来评估网络,给网络输入测试集合,测试集表示网络从没有接触过的新图像。从而测试网络的准确率。

    model.compile(optimizer = tf.train.AdamOptimizer(),
                  loss = 'sparse_categorical_crossentropy')
    
    model.fit(training_images, training_labels, epochs=5)
    model.evaluate(test_images, test_labels)
    
    2.实现简单的卷积神经网络

    卷积神经网络主要的层是卷积层和池化层。Conv2D第一个参数是希望生成的滤波器的数量,可以任意设置,但最好以32的倍数。第二个参数是滤波器的尺寸。第三个参数的激活函数,激活函数采用relu是因为在图像中像素不能为负数,所有relu保证了将所有的负数置为0。第四个参数为输入数据的尺寸,第一层的尺寸为图像的尺寸。MaxPooling2D池化层是将图像进行压缩,只保留每个池化块中的最大值。

    model = tf.keras.models.Sequential([
      tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(28, 28, 1)),
      tf.keras.layers.MaxPooling2D(2, 2),
      tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
      tf.keras.layers.MaxPooling2D(2,2),
      tf.keras.layers.Flatten(),
      tf.keras.layers.Dense(128, activation='relu'),
      tf.keras.layers.Dense(10, activation='softmax')
    ])
    
    卷积、池化

    通过下图可以看到模型每层的参数,第一层的卷积层输入的是(28,28,1),但是输出的(26,26,1)。这是因为卷积时没有进行边缘填充,所有左右上下更少了一个像素。池化层是(2,2),所以图像尺寸变为原来的一半。


    模型参数
    3.使用卷积神经网络处理真实图片

    真实图像相比数据集更加复杂,且像素更多,因此构建一个5层的卷积网络,初始输入尺寸为(300,300,3)。在这个数据集中,图像为二分类问题,所以最后输出层只需要一个神经元,输出的是0-1的之间的数,表示概率。概率越接近1,表示图像为人的概率越大,概率越接近0,表示图像为马的概率越大。输出层的激活函数为sigmoid

    model = tf.keras.models.Sequential([
        tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(300, 300, 3)),
        tf.keras.layers.MaxPooling2D(2, 2),
        
        tf.keras.layers.Conv2D(32, (3,3), activation='relu'),
        tf.keras.layers.MaxPooling2D(2,2),
        
        tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
        tf.keras.layers.MaxPooling2D(2,2),
        
        tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
        tf.keras.layers.MaxPooling2D(2,2),
        
        tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
        tf.keras.layers.MaxPooling2D(2,2),
       
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(512, activation='relu'),
        tf.keras.layers.Dense(1, activation='sigmoid')
    ])
    

    使用keras中的图像处理类来处理图像,ImageDataGenerator是keras.preprocessing.image模块中的图片生成器,可以每一次给模型“喂”一个batch_size大小的样本数据,同时也可以在每一个批次中对这batch_size个样本数据进行增强,扩充数据集大小,增强模型的泛化能力。比如进行旋转,变形,归一化等等。
    因为神经网络的输入尺寸定义为(300,300,3),所以这里需要将图像的尺寸定义为(300,300)。每个batch定义为128张图片。因为上面神经网络采用的损失函数是binary_crossentropy,所以我们需要二分类的标签。

    from tensorflow.keras.preprocessing.image import ImageDataGenerator
    
    train_datagen = ImageDataGenerator(rescale=1/255)
    
    train_generator = train_datagen.flow_from_directory(
            '/tmp/horse-or-human/', 
            target_size=(300, 300), 
            batch_size=128,
            class_mode='binary')
    

    使用fit_generator训练模型。verbose:日志显示。verbose = 0 为不在标准输出流输出日志信息。verbose = 1 为输出进度条记录。verbose = 2 为每个epoch输出一行记录。注意: 默认为 1。

    history = model.fit_generator(
          train_generator,
          steps_per_epoch=8,  
          epochs=15,
          verbose=1)
    

    最后使用model.predict来对需要检测的图片进行测试。对于输出的概率使用0.5最为分解数值,大于0.5判断为人,小于0.5判断为马。

    相关文章

      网友评论

          本文标题:keras CNN入门(一)

          本文链接:https://www.haomeiwen.com/subject/gsdujktx.html