今天我们将学习如何使用 TensorFlow 中 Keras 构建卷积神经网络来识别图片来区分出哪个是猫哪个是狗。
查看 Keras 版本
为什么使用 Keras 而不是 TensorFlow,这是因为 TensorFlow 相对于 Keras 要更复杂些,更通用一些,可以做一些 DeepLearning 以为事情,而 keras 则更专业更专注做 DeepLearning 的事情
图from tensorflow import keras
print(keras.__version__)
其实 Keras 可以理解为 TensorFlow 和 theano 的接口,提供更高级 Api 供开发者使用。提供深度学习常用算法。
Keras 开始是独立的,是独立于 TensorFlow 的库,不过现在已经被纳入 TensorFlow 官方的 Api 中。
加载数据,这我们获取图片是从微软提供资源进行机器学习
https://www.microsoft.com/en-us/download/confirmation.aspx?id=54765
import numpy as np
import matplotlib.pyplot as plt
import os
import cv2
cv 是对图片进行处理,os 操作文件路径,而 matplotlib 用于将图片可视化。加载后将图片解压到 images_data/PetImages
图
DATA_DIR = "images_data/PetImages"
CATEGORIES = ["Dog","Cat"]
for category in CATEGORIES:
path = os.path.join(DATA_DIR,category)
# print(path)
for img in os.listdir(path):
print(img)
img_array = cv2.imread(os.path.join(path,img),cv2.IMREAD_GRAYSCALE)
plt.imshow(img_array,cmap="gray")
plt.show()
break
break
显示第一张图片,这是一张 Dog 图片 cv2.IMREAD_GRAYSCALE 将图片转换为黑白照片,因为识别 Dog ,颜色对识别作用并不大,所以这里所以忽略图片
图
print(img_array.shape)
(500, 333)
从图片上来看,图片大小和方向都不一致,有图图片是长方形,有的图片是正方形。
IMG_SIZE = 50
new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))
plt.imshow(new_array,cmap='gray')
plt.show()
我们对图片进行一些处理,图片尺寸缩减为 50 ,调整一个图片大小尽量小,而且可从中判断出 Dog。
图
我们需要基于图片创建出适合训练机器学习的数据集,下面是整理出数据集方法函数会创建出带有标签的数据集
training_data = []
def create_training_data():
for category in CATEGORIES:
print(category)
path = os.path.join(DATA_DIR,category)
class_num = CATEGORIES.index(category)
# print(path)
for img in 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
create_training_data()
print(len(training_data))
12476
创建好的数据集是狗狗图片和猫图片是没有被打乱的这样是不适合机器学习的。所以我们 shuffle 循序来让机器通过读取图片数据进行学习。
import random
random.shuffle(training_data)
for sample in training_data[:10]:
print(sample[1])
X = []
y = []
for features, label in training_data:
X.append(features)
y.append(label)
X = np.array(X).reshape(-1,IMG_SIZE,IMG_SIZE,1)
处理好的图片数据可以保存到 X.pickle 和 y.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()
加下来我们就可以使用这些数据通过卷积神经网络来训练我们模型,要训练模型首先需要设计模型。
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten, Conv2D, MaxPooling2D
首先需要引入必要库,这里使用 keras 来迅速搭建我们神经网络。
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import pickle
X = pickle.load(open("X.pickle","rb"))
y = pickle.load(open("y.pickle","rb"))
加载了之前处理数据,这些数据是我们之前处理过保存的数据。
X = X/255.0
model = Sequential()
创建 Sequential 模型也就是我们模型是循序执行,也就是神经网络层有前后循序,可能是为了区别于 RNN 模型吧。
model.add(Conv2D(64,(3,3),input_shape = X.shape[1:]))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(2,2)))
现在创建卷积层,卷积核为 3 * 3 使用简单激活函数 relu 然后紧跟卷积层后面是池化层,池化层的大小给 2 * 2
model.add(Conv2D(64,(3,3)))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(2,2)))
然后是卷积核的 Filter Map 进行压缩为一维矩阵数据供下一层使用。
model.add(Flatten())
model.add(Dense(64))
首先将多维数据压缩为一维数据,作为输入数据。Dense 表示一个全连接的层,这也就是我们要添加一个输出 64 的全连接层。然后activation 可以指定激活函数。
model.add(Dense(1))
model.add(Activation("sigmoid"))
最后开始训练我们设计好的模型,接下来评价我们模型,可以指定 loss 函数类型,训练模型就是找到最合适方程,可以在 optimizer 指定找到最合适函数的方式。
model.compile(loss="binary_crossentropy",optimizer="adam",metrics=['accuracy'])
model.fit(X,y, batch_size=32, validation_split=0.1)
开始训练,第一个参数为训练集,y_train 为期望值,x_train 是二维数组,一维是训练集样本数量,第二个维度是图片大小,50 * 50 = 2500。对于 y_train 的第一个维度就是样本的数量,第二个就是 10 维,因为我们图片是分为 2 类。
图其实这里还有参数batch_size 指定数量,这样 keras 是根据 batch_size 将数据进行划分,然后在 batch_size 计算出 loss 函数得到然后根据 loss 函数结构调整一次参数依次类推,每一个 batch 都会根据loss 函数来更新参数
图 图
然后每完成一次所有 batch 运算就算为 epoch
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten, Conv2D, MaxPooling2D
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import pickle
X = pickle.load(open("X.pickle","rb"))
y = pickle.load(open("y.pickle","rb"))
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())
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, validation_split=0.1)
8288/22451 [==========>...................] - ETA: 49s - loss: 0.6810 - acc: 0.5537
al_loss: 0.5551 - val_acc: 0.7234
model.fit(X,y, batch_size=32, epochs=3, validation_split=0.1)
Epoch 1/3
22451/22451 [==============================] - 74s 3ms/sample - loss: 0.6064 - acc: 0.6638 - val_loss: 0.5413 - val_acc: 0.7238
Epoch 2/3
22451/22451 [==============================] - 74s 3ms/sample - loss: 0.5150 - acc: 0.7499 - val_loss: 0.4941 - val_acc: 0.7643
Epoch 3/3
22451/22451 [==============================] - 73s 3ms/sample - loss: 0.4804 - acc: 0.7728 - val_loss: 0.4708 - val_acc: 0.7756
网友评论