100天搞定机器学习|1-38天

100天搞定机器学习|day39 Tensorflow Keras手写数字识别

前文我们用keras的Sequential 模型实现mnist手写数字识别,准确率0.9713。今天我们完成day40-42的课程,实现猫、狗的识别。

本文数据集下载地址

https://download.microsoft.com/download/3/E/1/3E1C3F21-ECDB-4869-8368-6DEBA77B919F/kagglecatsanddogs_3367a.zip

本文需要用到OpenCV和Tqdm。OpenCV是跨平台计算机视觉库,可以实现了图像处理和计算机视觉方面的很多通用算法。Tqdm是用来显示进度条的,使用很直观(在循环体里边加个tqdm),基本不影响原程序效率。安装都很简单,只需要pip install即可:

1、数据预处理

数据集各有12501张猫和狗的图像,先对这些图像进行尺寸统一和颜色处理。

导入库

import numpy as np
import matplotlib.pyplot as plt
import osimport cv2
from tqdm import tqdm

看一张转换后的图片

DATADIR = "...\\PetImages" # 数据集的路径,请根据需要修改
CATEGORIES = ["Dog", "Cat"]
for category in CATEGORIES:     
path = os.path.join(DATADIR,category)  # 创建路径    
for img in os.listdir(path):  # 迭代遍历每个图片
        img_array = cv2.imread(os.path.join(path,img) ,cv2.IMREAD_GRAYSCALE)  # 转化成array
        plt.imshow(img_array, cmap='gray')  # 转换成图像展示
        plt.show()  # display!
        break  # 我们作为演示只展示一张,所以直接break了    break  #同上

看下array中存储的图像数据:

print(img_array)

[[117 117 119 … 133 132 132]

[118 117 119 … 135 134 134]

[119 118 120 … 137 136 136]



[ 79  74  73 …  80  76  73]

[ 78  72  69 …  72  73  74]

[ 74  71  70 …  75  73  71]]

看下array的形状:

print(img_array.shape)

(375, 500)

我们可以看到这是一张很大的图片,并且拥有RGB3个通道,这并不是我们想要的,所以接下来我们将要进行的操作会使图像变小,并且只剩下灰度:

IMG_SIZE = 50
new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))
plt.imshow(new_array, cmap='gray')
plt.show()

SIZE设置成50有一些模糊,尝试下100:

IMG_SIZE = 100
new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))
plt.imshow(new_array, cmap='gray')
plt.show()

接下来,我们将要创建所有这些培训数据,但是,首先,我们应该留出一些图像进行最终测试。我将手动创建一个名为Testing的目录,然后在其中创建2个目录,一个用于Dog,一个用于Cat。从这里开始,我将把Dog和Cat的前15张图像移到训练版本中。确保移动它们,而不是复制。我们将使用它进行最终测试。

training_data = []
def create_training_data():
    for category in CATEGORIES: 
         path = os.path.join(DATADIR,category)
          class_num = CATEGORIES.index(category)  # 得到分类,其中 0=dog 1=cat
        for img in tqdm(os.listdir(path)):
              try: 
               img_array = cv2.imread(os.path.join(path,img) ,cv2.IMREAD_GRAYSCALE) 
                 new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))  # 大小转换
                training_data.append([new_array, class_num])  # 加入训练数据中
            except Exception as e:  # 为了保证输出是整洁的
                pass            #except OSError as e: 
           #    print("OSErrroBad img most likely", e, os.path.join(path,img)) 
           #except Exception as e: 
           #    print("general exception", e, os.path.join(path,img))create_training_data()print(len(training_data))

100%|██████████| 12501/12501 [00:36<00:00, 342.82it/s]

100%|██████████| 12501/12501 [00:39<00:00, 320.35it/s]

24946

我们有大约25,000张图片。

我们要做的一件事是确保我们的数据是平衡的。在这个数据集的情况下,我可以看到数据集开始时是平衡的。平衡,我的意思是每个班级都有相同数量的例子(相同数量的狗和猫)。如果不平衡,要么将类权重传递给模型,以便它可以适当地测量误差,或者通过将较大的集修剪为与较小集相同的大小来平衡样本。

现在数据集中要么全是dog要么全是cat,因此接下来要引入随机:

import random
random.shuffle(training_data)

我们的training_data是一个列表,这意味着它是可变的,所以它现在很好地改组了。我们可以通过迭代几个初始样本并打印出类来确认这一点:

for sample in training_data[:10]: 
   print(sample[1])

0

1

0

1

1

0

1

0

1

0

现在可以看到已经是0、1交替了,我们可以开始我们的模型了:

X = []
y = []
for features,label in training_data:
    X.append(features)
    y.append(label)
print(X[0].reshape(-1, IMG_SIZE, IMG_SIZE, 1))
X = np.array(X).reshape(-1, IMG_SIZE, IMG_SIZE, 1)

让我们保存这些数据,这样我们就不需要每次想要使用神经网络模型时继续计算它:

import pickle
pickle_out = open("...\\X.pickle","wb")
pickle.dump(X, pickle_out)pickle_out.close()
pickle_out = open("...\\y.pickle","wb")
pickle.dump(y, pickle_out)pickle_out.close()
# We can always load it in to our current script, or a totally new one by doing:
pickle_in = open("...\\X.pickle","rb")
X = pickle.load(pickle_in)
pickle_in = open("...\\y.pickle","rb")
y = pickle.load(pickle_in)

现在我们已经拿出了数据集,我们已经准备好覆盖卷积神经网络,并用我们的数据进行分类。

以上就是这次的关于数据集操作的全部任务。


2、训练模型

基础知识

基本的CNN结构如下:Convolution(卷积) -> Pooling(池化) -> Convolution -> Pooling -> Fully Connected Layer(全连接层) -> Output

Convolution(卷积)是获取原始数据并从中创建特征映射的行为。Pooling(池化)是下采样,通常以“max-pooling”的形式,我们选择一个区域,然后在该区域中取最大值,这将成为整个区域的新值。Fully Connected Layers(全连接层)是典型的神经网络,其中所有节点都“完全连接”。卷积层不像传统的神经网络那样完全连接。

卷积:我们将采用某个窗口,并在该窗口中查找要素,该窗口的功能现在只是新功能图中的一个像素大小的功能,但实际上我们将有多层功能图。接下来,我们将该窗口滑过并继续该过程,继续此过程,直到覆盖整个图像。

池化:最常见的池化形式是“最大池化”,其中我们简单地获取窗口中的最大值,并且该值成为该区域的新值。

全连接层:每个卷积和池化步骤都是隐藏层。在此之后,我们有一个完全连接的层,然后是输出层。完全连接的层是典型的神经网络(多层感知器)类型的层,与输出层相同。

注意

本次代码中所需的X.pickle和y.pickle为上一篇的输出,路径请根据自己的情况更改!

此篇中文为译者根据原文整理得到,可能有不当之处,可以点击此处查看原文。

import tensorflow as tf
from tensorflow.keras.datasets import cifar10
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten
from tensorflow.keras.layers import Conv2D, MaxPooling2D import pickle pickle_in = open("../datasets/X.pickle","rb")
X = pickle.load(pickle_in) pickle_in = open("../datasets/y.pickle","rb")
y = pickle.load(pickle_in) X = X/255.0 model = Sequential() model.add(Conv2D(256, (3, 3), input_shape=X.shape[1:]))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(256, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) # this converts our 3D feature maps to 1D feature vectors model.add(Dense(64)) model.add(Dense(1))
model.add(Activation('sigmoid')) model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy']) model.fit(X, y, batch_size=32, epochs=3, validation_split=0.3)

Train on 17462 samples, validate on 7484 samples

Epoch 1/3

step - loss: 0.6728 - acc: 0.6019 - val_loss: 0.6317 - val_acc: 0.6463

Epoch 2/3

step - loss: 0.6164 - acc: 0.6673 - val_loss: 0.6117 - val_acc: 0.6776

Epoch 3/3

step - loss: 0.5690 - acc: 0.7129 - val_loss: 0.5860 - val_acc: 0.6963

在仅仅三个epoches之后,我们的验证准确率为71%。如果我们继续进行更多的epoches,我们可能会做得更好,但我们应该讨论我们如何知道我们如何做。为了解决这个问题,我们可以使用TensorFlow附带的TensorBoard,它可以帮助在训练模型时可视化模型。

3、模型调参

在这一部分,我们将讨论的是TensorBoard。TensorBoard是一个方便的应用程序,允许在浏览器中查看模型或模型的各个方面。我们将TensorBoard与Keras一起使用的方式是通过Keras回调。实际上有很多Keras回调,你可以自己制作。

from tensorflow.keras.callbacks import TensorBoard
#创建TensorBoard回调对象
NAME = "Cats-vs-dogs-CNN" tensorboard = TensorBoard(log_dir="logs/{}".format(NAME))

最终,你会希望获得更多的自定义NAME,但现在这样做。因此,这将保存模型的训练数据logs/NAME,然后由TensorBoard读取。

最后,我们可以通过将它添加到.fit方法中来将此回调添加到我们的模型中,例如:

model.fit(X, y,
batch_size=32,
epochs=3,
validation_split=0.3,
callbacks=[tensorboard])

请注意,这callbacks是一个列表。也可以将其他回调传递到此列表中。我们的模型还没有定义,所以现在让我们把它们放在一起:

import tensorflow as tf
from tensorflow.keras.datasets import cifar10
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten
from tensorflow.keras.layers import Conv2D, MaxPooling2D
from tensorflow.keras.callbacks import TensorBoard
# more info on callbakcs: https://keras.io/callbacks/ model saver is cool too.
import pickle
import time NAME = "Cats-vs-dogs-CNN" pickle_in = open("../datasets/X.pickle","rb")
X = pickle.load(pickle_in) pickle_in = open("../datasets/y.pickle","rb")
y = pickle.load(pickle_in) X = X/255.0 model = Sequential() model.add(Conv2D(256, (3, 3), input_shape=X.shape[1:]))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(256, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) # this converts our 3D feature maps to 1D feature vectors
model.add(Dense(64)) model.add(Dense(1))
model.add(Activation('sigmoid')) tensorboard = TensorBoard(log_dir="logs/{}".format(NAME)) model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'],
) model.fit(X, y,
batch_size=32,
epochs=3,
validation_split=0.3,
callbacks=[tensorboard])

Train on 17462 samples, validate on 7484 samples

Epoch 1/3

step - loss: 0.6992 - acc: 0.5480 - val_loss: 0.6900 - val_acc: 0.5274

Epoch 2/3

step - loss: 0.6754 - acc: 0.5782 - val_loss: 0.6685 - val_acc: 0.5885

Epoch 3/3

step - loss: 0.6377 - acc: 0.6483 - val_loss: 0.6217 - val_acc: 0.6625

运行此之后,应该有一个名为的新目录logs。我们现在可以使用tensorboard从这个目录中可视化初始结果。打开控制台,切换到工作目录,然后键入:tensorboard --logdir=logs/。应该看到一个通知:TensorBoard 1.10.0 at http://H-PC:6006 (Press CTRL+C to quit)“h-pc”是机器的名称。打开浏览器并前往此地址。你应该看到类似的东西:

现在我们可以看到我们的模型随着时间的推移。让我们改变模型中的一些东西。首先,我们从未在密集层中添加激活。另外,让我们尝试整体较小的模型:

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten
from tensorflow.keras.layers import Conv2D, MaxPooling2D
from tensorflow.keras.callbacks import TensorBoard
# more info on callbakcs: https://keras.io/callbacks/ model saver is cool too.
import pickle
import time NAME = "Cats-vs-dogs-64x2-CNN" pickle_in = open("../datasets/X.pickle","rb")
X = pickle.load(pickle_in) pickle_in = open("../datasets/y.pickle","rb")
y = pickle.load(pickle_in) X = X/255.0 model = Sequential() model.add(Conv2D(64, (3, 3), input_shape=X.shape[1:]))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) # this converts our 3D feature maps to 1D feature vectors
model.add(Dense(64))
model.add(Activation('relu')) model.add(Dense(1))
model.add(Activation('sigmoid')) tensorboard = TensorBoard(log_dir="logs/{}".format(NAME)) model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'],
) model.fit(X, y,
batch_size=32,
epochs=10,
validation_split=0.3,
callbacks=[tensorboard])

除此之外,我还改名为NAME = "Cats-vs-dogs-64x2-CNN"。不要忘记这样做,否则你会偶然附加到你以前的型号的日志,它看起来不太好。我们现在检查TensorBoard:

看起来更好!但是,可能会立即注意到验证丢失的形状。损失是衡量错误的标准,看起来很明显,在我们的第四个时代之后,事情开始变得糟糕。

有趣的是,我们的验证准确性仍然持续,但我想它最终会开始下降。更可能的是,第一件遭受的事情确实是你的验证损失。这应该提醒你,你几乎肯定会开始过度适应。这种情况发生的原因是该模型不断尝试减少样本损失。

在某些时候,模型不是学习关于实际数据的一般事物,而是开始只记忆输入数据。如果你继续这样做,是的,样本中的“准确性”会上升,但你的样本,以及你试图为模型提供的任何新数据可能会表现得很差。

参考

https://github.com/MLEveryday/100-Days-Of-ML-Code/blob/master/Code/Day 40.ipynb

https://github.com/MLEveryday/100-Days-Of-ML-Code/blob/master/Code/Day 41.ipynb

https://github.com/MLEveryday/100-Days-Of-ML-Code/blob/master/Code/Day 42.ipynb

100天搞定机器学习|day40-42 Tensorflow Keras识别猫狗的更多相关文章

  1. 100天搞定机器学习:PyYAML基础教程

    编程中免不了要写配置文件,今天我们继续Python网络编程,学习一个比 JSON 更简洁和强大的语言----YAML .本文老胡简单介绍 YAML 的语法和用法,以及 YAML 在机器学习项目中的应用 ...

  2. 100天搞定机器学习|Day7 K-NN

    最近事情无比之多,换了工作.组队参加了一个比赛.和朋友搞了一些小项目,公号荒废许久.坚持是多么重要,又是多么艰难,目前事情都告一段落,我们继续100天搞定机器学习系列.想要继续做这个是因为,一方面在具 ...

  3. 100天搞定机器学习|Day11 实现KNN

    机器学习100天|Day1数据预处理 100天搞定机器学习|Day2简单线性回归分析 100天搞定机器学习|Day3多元线性回归 100天搞定机器学习|Day4-6 逻辑回归 100天搞定机器学习|D ...

  4. 100天搞定机器学习|Day8 逻辑回归的数学原理

    机器学习100天|Day1数据预处理 100天搞定机器学习|Day2简单线性回归分析 100天搞定机器学习|Day3多元线性回归 100天搞定机器学习|Day4-6 逻辑回归 100天搞定机器学习|D ...

  5. 100天搞定机器学习|Day9-12 支持向量机

    机器学习100天|Day1数据预处理 100天搞定机器学习|Day2简单线性回归分析 100天搞定机器学习|Day3多元线性回归 100天搞定机器学习|Day4-6 逻辑回归 100天搞定机器学习|D ...

  6. 100天搞定机器学习|Day16 通过内核技巧实现SVM

    前情回顾 机器学习100天|Day1数据预处理100天搞定机器学习|Day2简单线性回归分析100天搞定机器学习|Day3多元线性回归100天搞定机器学习|Day4-6 逻辑回归100天搞定机器学习| ...

  7. 100天搞定机器学习|Day17-18 神奇的逻辑回归

    前情回顾 机器学习100天|Day1数据预处理 100天搞定机器学习|Day2简单线性回归分析 100天搞定机器学习|Day3多元线性回归 100天搞定机器学习|Day4-6 逻辑回归 100天搞定机 ...

  8. 100天搞定机器学习|Day19-20 加州理工学院公开课:机器学习与数据挖掘

    前情回顾 机器学习100天|Day1数据预处理 100天搞定机器学习|Day2简单线性回归分析 100天搞定机器学习|Day3多元线性回归 100天搞定机器学习|Day4-6 逻辑回归 100天搞定机 ...

  9. 100天搞定机器学习|Day21 Beautiful Soup

    前情回顾 机器学习100天|Day1数据预处理 100天搞定机器学习|Day2简单线性回归分析 100天搞定机器学习|Day3多元线性回归 100天搞定机器学习|Day4-6 逻辑回归 100天搞定机 ...

随机推荐

  1. 快速掌握mongoDB(三)——mongoDB的索引详解

    1 mongoDB索引的管理 本节介绍mongoDB中的索引,熟悉mysql/sqlserver等关系型数据库的小伙伴应该都知道索引对优化数据查询的重要性.我们先简单了解一下索引:索引的本质就是一个排 ...

  2. C#窗体实现打开关闭VM虚拟机

    vixclass.cs//定义开机.关机等函数 using System; using System.Collections.Generic; using System.Linq; using Sys ...

  3. 通过自研数据库画像工具支持“去O”评估

    “去O”,是近些年来一直很火的一个话题,随之也产生了各种疑惑,包括现有数据库评估.技术选型等.去O是项系统工程,需要做好充分的评估.本文通过自研工具,生成数据库画像,为去O评估提供一手数据,希望给大家 ...

  4. git的使用之eclipse Hbuilder

    工欲善其事,必先利其器 eclipse使用git管理项目 准备 eclipse 码云(github)账号 下载插件 首先电脑已经安装好git了,然后在eclipse中下载git的插件. 打开eclip ...

  5. fjnu2016-2017 低程 PROBLEM C 汪老司机

    动态规划 方程 #include <iostream>#include <iomanip>#include <cmath>#include <algorith ...

  6. [git] 基础命令笔记

    --内容整理自廖雪峰的GIT教程-- git status 查看当前工作区状态,显示未跟踪的文件以及未上传的修改记录 git init 使当前文件夹变成Git可以管理的仓库 git add xxx 将 ...

  7. SYNPROXY:廉价的抗DoS攻击方案

    DoS攻击是一个永恒的问题,虽然专业厂商的防火墙,负载均衡类的网关设备能比较有效的防御DoS攻击,但黑客们更倾向于x86+GNU/Linux的组合,原因很简单:足够的廉价. 在linux内核3.13里 ...

  8. luogu题解 P5020 【货币系统 】

    思路 判断钱数是否可以转化为其他钱数的和 与楼下不同,我没有用sort.而是用了一个数组来特判. 思路其实只是简单dp. 详见代码. #include<cstdio> using name ...

  9. 支持微信页面右侧悬浮QQ在线客服

    使用方法: 1.将style里的css样式复制到你的样式表中 2.将body中的代码部分拷贝到你需要的地方即可 (js.图片采用绝对路径,不建议修改) <!DOCTYPE html PUBLIC ...

  10. Apache SSI 远程命令执行漏洞复现

    Apache SSI 远程命令执行漏洞复现 一.漏洞描述 当目标服务器开启了SSI与CGI支持,我们就可以上传shtml,利用<!--#exec cmd=”id” -->语法执行命令. 使 ...