包含一个或多个卷积层(Convolutional Layer)、池化层(Pooling Layer)和全连接层(Fully-connected Layer)。
卷积:
https://pic.rmb.bdstatic.com/e6871b1259fe02a5192e15294fc684148433.gif
https://img-blog.csdnimg.cn/20181124130023841.gif
池化:
参数描述:
inputs:把上一层的输出作为输入(直接将上一层作为参数输入即可)
input_shape:当作为模型的第一层时,需要指出输入的形状(samples,rows,cols,channels) ,只指出后三维即可,第一维度按batch_size自动指定
filters:卷积过滤器的数量,对应输出的维数
kernel_size:整数,过滤器的大小,如果为一个整数则宽和高相同
strides:横向和纵向的步长,如果为一个整数则横向和纵向相同
padding:valid(默认):表示不够卷积核大小的块,则丢弃;same表示不够卷积核大小的块就补0(右下和左下填充,如果只填充一列(一行)就足够了,那么默认在最后一行之后和最后一列之后填充。)
data_format:channels_last为(batch,height,width,channels),channels_first为(batch,channels,height,width)
dilation_rate:整数,空洞卷积的间隔
activation:激活函数,None是线性函数
use_bias:是否使用偏差量
kernel_initializer:卷积核的初始化。
bias_initializer:偏差向量的初始化。如果是None,则使用默认的初始值。
kernel_regularizer:卷积核的正则项
bias_regularizer:偏差向量的正则项
activity_regularizer:输出的正则函数
bias_constraint:映射函数,当偏差向量被Optimizer更新后应用到偏差向量上。
trainable:Boolean类型。
name:字符串,层的名字。
reuse:Boolean类型,表示是否可以重复使用具有相同名字的前一层的权重。
最大池化:tf.keras.layers.MaxPool2D
平均池化:tf.keras.layers.AveragePooling2D
在tensorflow中的conv2d中,
input的四个维度是[batch, in_height, in_width, in_channels],
filter的四个维度是[filter_height, filter_width, in_channels, out_channels]。
filter的通道数(深度)与输入层的通道数(深度)是一致的,就是in_channels!!!
filter中out_channels数值 (输出通道数)= filter的数量
输入矩阵W*H
filter矩阵F*F
stride值S,步长
输出宽高为new_height,new_width
new_height = (W - F + 1) / S (结果向上取整)
new_width = (H - F + 1) / S (结果向上取整)
import tensorflow as tf
input_data = tf.random.uniform((1,3,4,3))
input_data.shape
TensorShape([1, 3, 4, 3])
conv1 = tf.keras.layers.Conv2D(filters=3, kernel_size=(2,2), strides=(1,1), padding='valid',
activation='relu')
new_height = (H - F + 1) / S = (3-2+1)/1 = 2
new_width = (W - F + 1) / S = (4-2+1)/1 = 3
conv1(input_data)
new_height = H / S(结果向上取整)
new_width = W / S(结果向上取整)
conv2 = tf.keras.layers.Conv2D(filters=1, kernel_size=(2,2), strides=(1,1), padding='same',
activation='relu')
new_height = H / S = 3/1 = 3
new_width = W / S = 4/1 = 4
conv2(input_data)
数据集下载:
链接:https://pan.baidu.com/s/1__W9Zl4A3H8szCQTWwiE9Q
提取码:fvrq
需要安装的包:
pip install opencv-python
import cv2
import os
import tensorflow as tf
import numpy as np
数据集路径—根据自己的路径进行改写
path=r'flower_photos/'
由于我们的数据集图片大小不一致,所以需要resize成统一大小 这里resize成100x100x3
w=100
h=100
c=3
读取数据集图片并添加标签,最后的形式是data 对应图片, label 是标签,roses 0,daisy 1,sunflowers 2,tulips 3,dandelion 4.
def read_img(path):
imgs=[]
labels=[]
cate=[path+x for x in os.listdir(path) if os.path.isdir(path+x)]
for idx,i in enumerate(cate):
for j in os.listdir(i):
im = cv2.imread(i+'/'+j)
img = cv2.resize(im, (w, h))/255.
#print('reading the images:%s'%(i+'/'+j))
imgs.append(img)
labels.append(idx)
return np.asarray(imgs,np.float32),np.asarray(labels,np.int32)
data,label=read_img(path)
将数据集打乱顺序
num_example=data.shape[0] # data.shape是(3029, 100, 100, 3)
arr=np.arange(num_example)# 创建等差数组 0,1,...,3028
np.random.shuffle(arr)# 打乱顺序
data=data[arr]
label=label[arr]
print(label)
[4 1 3 ... 4 2 3]
标签one-hot处理
def to_one_hot(label):
return tf.one_hot(label,5)
label_oh = to_one_hot(label)
将所有数据集分为训练集80%、测试集20%
ratio=0.8
s=np.int(num_example*ratio)
x_train=data[:s]
y_train=label_oh.numpy()[:s]
x_val=data[s:]
y_val=label_oh.numpy()[s:]
x_train.shape
(2936, 100, 100, 3)
# model = tf.keras.Sequential([
# tf.keras.layers.Conv2D(filters=32, input_shape=(28,28,1),kernel_size=(3,3), strides=(1,1), padding='valid',
# activation='relu'),
# tf.keras.layers.MaxPool2D(pool_size=(2,2)),
# tf.keras.layers.Flatten(),
# tf.keras.layers.Dense(32, activation='relu'),
# tf.keras.layers.Dense(10, activation='softmax')
# ])
# model = tf.keras.Sequential()
# model.add(tf.keras.layers.Conv2D(input_shape=(x_train.shape[1], x_train.shape[2], x_train.shape[3]),
# filters=32, kernel_size=(3,3), strides=(1,1), padding='valid',
# activation='relu'))
# model.add(tf.keras.layers.MaxPool2D(pool_size=(2,2)))
# model.add(tf.keras.layers.Flatten())
# model.add(tf.keras.layers.Dense(32, activation='relu'))
# # 分类层
# model.add(tf.keras.layers.Dense(10, activation='softmax'))
class CNN(tf.keras.Model):
def __init__(self):
super().__init__()
self.conv1 = tf.keras.layers.Conv2D(
filters=64, # 卷积层神经元(卷积核)数目
kernel_size=[3, 3], # 感受野大小
padding='valid', # padding策略(vaild 或 same)
activation=tf.nn.relu # 激活函数
)
self.pool1 = tf.keras.layers.MaxPool2D(pool_size=[2, 2], strides=1)
self.conv2 = tf.keras.layers.Conv2D(
filters=32,
kernel_size=[5, 5],
padding='valid',
activation=tf.nn.relu
)
self.pool2 = tf.keras.layers.MaxPool2D(pool_size=[2, 2], strides=2)
self.flatten = tf.keras.layers.Flatten()
self.dense1 = tf.keras.layers.Dense(units=128, activation=tf.nn.relu)
self.dense2 = tf.keras.layers.Dense(units=5)
def call(self, inputs):
x = self.conv1(inputs)
x = self.pool1(x)
x = self.flatten(x)
x = self.dense1(x)
x = self.dense2(x)
output = tf.nn.softmax(x)
return output
model = CNN()
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
loss = tf.keras.losses.categorical_crossentropy,
metrics=[tf.keras.metrics.categorical_accuracy])
history = model.fit(x_train, y_train, batch_size=64, epochs=10, validation_split=0.2)
Train on 2348 samples, validate on 588 samples
Epoch 1/10
2348/2348 [==============================] - 29s 13ms/sample - loss: 11.3972 - categorical_accuracy: 0.3147 - val_loss: 1.3492 - val_categorical_accuracy: 0.4456
Epoch 2/10
2348/2348 [==============================] - 28s 12ms/sample - loss: 1.1495 - categorical_accuracy: 0.5486 - val_loss: 1.2279 - val_categorical_accuracy: 0.4541
Epoch 3/10
2348/2348 [==============================] - 28s 12ms/sample - loss: 0.9416 - categorical_accuracy: 0.6431 - val_loss: 1.0787 - val_categorical_accuracy: 0.5510
Epoch 4/10
2348/2348 [==============================] - 28s 12ms/sample - loss: 0.6518 - categorical_accuracy: 0.7777 - val_loss: 1.1170 - val_categorical_accuracy: 0.5374
Epoch 5/10
2348/2348 [==============================] - 29s 12ms/sample - loss: 0.4046 - categorical_accuracy: 0.8931 - val_loss: 1.1310 - val_categorical_accuracy: 0.5510
Epoch 6/10
2348/2348 [==============================] - 28s 12ms/sample - loss: 0.2228 - categorical_accuracy: 0.9476 - val_loss: 1.2393 - val_categorical_accuracy: 0.5544
Epoch 7/10
2348/2348 [==============================] - 29s 12ms/sample - loss: 0.1196 - categorical_accuracy: 0.9804 - val_loss: 1.2748 - val_categorical_accuracy: 0.5731
Epoch 8/10
2348/2348 [==============================] - 29s 12ms/sample - loss: 0.0756 - categorical_accuracy: 0.9889 - val_loss: 1.5054 - val_categorical_accuracy: 0.5408
Epoch 9/10
2348/2348 [==============================] - 29s 12ms/sample - loss: 0.0561 - categorical_accuracy: 0.9932 - val_loss: 1.5839 - val_categorical_accuracy: 0.5340
Epoch 10/10
2348/2348 [==============================] - 29s 12ms/sample - loss: 0.0388 - categorical_accuracy: 0.9966 - val_loss: 1.5596 - val_categorical_accuracy: 0.5510
model.evaluate(x_val,y_val,verbose=2)
734/1 - 2s - loss: 1.3128 - categorical_accuracy: 0.580
[1.460774506794984, 0.58038145]