CNN学习记录

配置环境

数据处理:导入数据(数据类型分好类)——设置训练集和测试集

模型构建:构建模型——编译模型——训练模型——评估模型

预测:预测图片

1、设置学习环境 TensorFlow,pytorch,Python版本

from tensorflow.keras

import keras

import os PIL pathlib

import tensorflow as tf

import numpy as np

import matplotlib.pyplot as plt

import layers,models

2、导入数据

import os

1 获得当前文件路径:os.getcwd() 2.新建一个文件夹:os.mkdir() 3.跳转当前文件路径:os.chdir(一个已存在的目录) 4.获得路径下的所有文件名称:os.listdir(path) 5.返回是否是文件夹:os.path.isdir() 6.返回是否是文件:os.path.isfile() 7.将文件路径进行拆分:os.path.split() 8.修改文件名称:os.rename()

import PIL PIL库是一个具有强大图像处理能力的第三方库,不仅包含了丰富的像素、色彩操作功能,还可以用于图像归档和批量处理。

import pathlib 导入路径库

import matplotlib.pyplot as plt 画图模块

import numpy NumPy系统是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵

from tensorflow.keras.regularizers import l2 正则化的主要作用是防止过拟合,对模型添加正则化项可以限制模型的复杂度,使得模型在复杂度和性能达到平衡。 L1正则化可以产生稀疏权值矩阵,即产生一个稀疏模型,可以用于特征选择,一定程度上,L1也可以防止过拟合 L2正则化可以防止模型过拟合(overfitting)

data.dir 数据地址

统计图片材料总数 data_dir image_count

查看图片 PIL.Image.open

import os,PIL,pathlib
import matplotlib.pyplot as plt
import numpy             as np
from tensorflow          import keras
from tensorflow.keras    import layers,models
data_dir = "数据文件地址"

data_dir = pathlib.Path(data_dir)

3、检查数据

归一化与标准化

归一化标准化是特征缩放的两种形式,其作用是:

  • 使不同量纲的特征处于同一数值量级,减少方差大的特征的影响,使模型更准确
  • 加快学习算法的收敛速度。

归一化是将数据“拍扁”统一到区间(仅由极值决定),而标准化是更加“弹性”和“动态”的,和整体样本的分布有很大的关系

  • 归一化:把数变为(0,1)之间的小数;缩放仅仅跟最大、最小值的差别有关。
  • 标准化:将数据按比例缩放,使之落入一个小的特定区间;缩放与每个点都有关

对于图片来说,由于max是255,min是0,也就是直接除以255就可以完成归一化。

# 将像素的值标准化至0到1的区间内。
train_images, test_images = train_images / 255.0, test_images / 255.0

标准化:将数据变换成均值为0,标准差为1的分布(但不一定为正态)

transforms.Normalize(mean = (0.485, 0.456, 0.406), std = (0.229, 0.224, 0.225))

查看数据

数据集一共分为cloudyrainshinesunrise四类,分别存放于weather_photos文件夹中以各自名字命名的子文件夹中。

image_count = len(list(data_dir.glob('*/*.jpg')))

print("图片总数为:",image_count)

打开文件中的一张图片

roses = list(data_dir.glob('sunrise/*.jpg'))
PIL.Image.open(str(roses[0]))

4、整理数据

设置一次处理的图片数目 设置图片的宽和高 batch_size image_height image_width

加载数据:使用image_dataset_from_directory方法将磁盘中的数据加载到tf.data.Dataset

# from tensorflow.keras.preprocessing import image_dataset_from_directory
 
tf.keras.preprocessing.image_dataset_from_directory(
    directory,
    labels="inferred",
    label_mode="int",
    class_names=None,
    color_mode="rgb",
    batch_size=32,
    image_size=(256, 256),
    shuffle=True,
    seed=None,
    validation_split=None,
    subset=None,
    interpolation="bilinear",
    follow_links=False,
)

从目录中的图像文件生成一个 tf.data.Dataset

如果你的目录结构是:

main_directory/
...class_a/
......a_image_1.jpg
......a_image_2.jpg
...class_b/
......b_image_1.jpg
......b_image_2.jpg

 然后调用 image_dataset_from_directory(main_directory, labels='inferred') 将返回一个tf.data.Dataset, 该数据集从子目录class_a和class_b生成批次图像,同时生成标签0和1(0对应class_a,1对应class_b).

支持的图像格式:jpeg, png, bmp, gif. 动图被截断到第一帧。

参数:

  • directory: 数据所在目录。如果标签是“inferred”(默认),则它应该包含子目录,每个目录包含一个类的图像。否则,将忽略目录结构。 
  • labels: “inferred”(标签从目录结构生成),或者是整数标签的列表/元组,其大小与目录中找到的图像文件的数量相同。标签应根据图像文件路径的字母顺序排序(通过Python中的os.walk(directory)获得)。
  • label_mode: 'int':表示标签被编码成整数(例如:sparse_categorical_crossentropy loss)。‘categorical’指标签被编码为分类向量(例如:categorical_crossentropy loss)。‘binary’意味着标签(只能有2个)被编码为值为0或1的float32标量(例如:binary_crossentropy)。None(无标签)。
  • class_names: 仅当“labels”为“inferred”时有效。这是类名称的明确列表(必须与子目录的名称匹配)。用于控制类的顺序(否则使用字母数字顺序)。
  • color_mode: "grayscale"、"rgb"、"rgba"之一。默认值:"rgb"。图像将被转换为1、3或者4通道。
  • batch_size: 数据批次的大小。默认值:32
  • image_size: 从磁盘读取数据后将其重新调整大小。默认:(256,256)。由于管道处理的图像批次必须具有相同的大小,因此该参数必须提供。
  • shuffle: 是否打乱数据。默认值:True。如果设置为False,则按字母数字顺序对数据进行排序。
  • seed: 用于shuffle和转换的可选随机种子。
  • validation_split: 0和1之间的可选浮点数,可保留一部分数据用于验证。
  • subset: "training"或"validation"之一。仅在设置validation_split时使用。
  • interpolation: 字符串,当调整图像大小时使用的插值方法。默认为:bilinear。支持bilinearnearestbicubicarealanczos3lanczos5gaussianmitchellcubic.。
  • follow_links: 是否访问符号链接指向的子目录。默认:False

有关生成图像中通道数量的规则:

如果color_mode 是 grayscale, 图像张量有1个通道。

如果color_mode 是 rgb, 图像张量有3个通道。

如果color_mode 是 rgba, 图像张量有4个通道。

设置训练集和测试集

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split = 0.1,
subset="training",
label_mode = "categorical",
seed = 123,
image_size=(image_height,image_width),
batch_size=batch_size)
Found 1800 files belonging to 17 classes.
Using 1620 files for training.
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split = 0.1,
subset="validation",
label_mode = "categorical",
seed = 123,
image_size=(image_height,image_width),
batch_size=batch_size)
Found 1800 files belonging to 17 classes.
Using 180 files for validation.

我们可以通过class_names输出数据集的标签。标签将按字母顺序对应于目录名称。

class_names = train_ds.class_names
print(class_names)
['Angelina Jolie', 'Brad Pitt', 'Denzel Washington', 'Hugh Jackman', 'Jennifer Lawrence', 'Johnny Depp', 'Kate Winslet', 'Leonardo DiCaprio', 'Megan Fox', 'Natalie Portman', 'Nicole Kidman', 'Robert Downey Jr', 'Sandra Bullock', 'Scarlett Johansson', 'Tom Cruise', 'Tom Hanks', 'Will Smith']

可视化数据:

# 将数据集前20个图片数据可视化显示
# 进行图像大小为20宽、10长的绘图(单位为英寸inch)
plt.figure(figsize=(20,10))
# 遍历MNIST数据集下标数值0~49
for i in range(20):
    # 将整个figure分成5行10列,绘制第i+1个子图。
    plt.subplot(2,10,i+1)
    # 设置不显示x轴刻度
    plt.xticks([])
    # 设置不显示y轴刻度
    plt.yticks([])
    # 设置不显示子图网格线
    plt.grid(False)
    # 图像展示,cmap为颜色图谱,"plt.cm.binary"为matplotlib.cm中的色表
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    # 设置x轴标签显示为图片对应的数字
    plt.xlabel(train_labels[i])
# 显示图片
plt.show()

检查数据和调整数据格式 train_images = train_images.reshape((32,224,224,1)) test_images = test_images.reshape((16,224,224,1))

for image_batch, labels_batch in train_ds:
    print(image_batch.shape)
    print(labels_batch.shape)
    break
(32, 180, 180, 3)
(32,)
  • Image_batch是形状的张量(32,180,180,3)。这是一批形状180x180x3的32张图片(最后一维指的是彩色通道RGB)。
  • Label_batch是形状(32,)的张量,这些标签对应32张图片
#调整数据到我们需要的格式
train_images = train_images.reshape((60000, 28, 28, 1))
test_images = test_images.reshape((10000, 28, 28, 1))

train_images.shape,test_images.shape,train_labels.shape,test_labels.shape
"""
输出:((60000, 28, 28, 1), (10000, 28, 28, 1), (60000,), (10000,))
"""

配置数据集

  • shuffle():打乱数据
  • prefetch():预取数据,加速运行
  • cache():将数据集缓存到内存当中,加速运行
AUTOTUNE = tf.data.AUTOTUNE

train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

5、构建模型

Sequential模型字面上的翻译是顺序模型,给人的第一感觉是那种简单的线性模型,但实际上Sequential模型可以构建非常复杂的神经网络,包括全连接神经网络、卷积神经网络(CNN)、循环神经网络(RNN)、等等。这里的Sequential更准确的应该理解为堆叠,通过堆叠许多层,构建出深度神经网络。
如下代码向模型添加一个带有64个大小为3 * 3的过滤器的卷积层:

from keras.models import Sequential
from keras.layers import Dense, Activation,Conv2D,MaxPooling2D,Flatten,Dropout

model = Sequential()
model.add(Conv2D(64, (3, 3), activation='relu'))

Sequential模型的核心操作是添加layers(图层),以下展示如何将一些最流行的图层添加到模型中:

  • 卷积层
model.add(Conv2D(64, (3, 3), activation='relu'))
  • 最大池化层
model.add(MaxPooling2D(pool_size=(2, 2)))
  • 全连接层
model.add(Dense(256, activation='relu'))
  • dropout
model.add(Dropout(0.5))
  • Flattening layer(展平层)
model.add(Flatten())

6、构建网络层

构建模型 sequential

顺序模型 VGG16_model = models.Sequential()

layers.Conv2D 卷积核个数,宽与高 ,padding,  input_shape ,正则化  ,activation 

layers.AveragePooling2D

layers.BatchNormalization()

layers.Dropout

layers.Flatten

layers.Dense

layers.Dense(num_classes)

model.summary()打印网格结构

# 创建并设置卷积神经网络
# 卷积层:通过卷积操作对输入图像进行降维和特征抽取
# 池化层:是一种非线性形式的下采样。主要用于特征降维,压缩数据和参数的数量,减小过拟合,同时提高模型的鲁棒性。
# 全连接层:在经过几个卷积和池化层之后,神经网络中的高级推理通过全连接层来完成。
model = models.Sequential([
    # 设置二维卷积层1,设置32个3*3卷积核,activation参数将激活函数设置为ReLu函数,input_shape参数将图层的输入形状设置为(28, 28, 1)
    # ReLu函数作为激活励函数可以增强判定函数和整个神经网络的非线性特性,而本身并不会改变卷积层
    # 相比其它函数来说,ReLU函数更受青睐,这是因为它可以将神经网络的训练速度提升数倍,而并不会对模型的泛化准确度造成显著影响。
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
    #池化层1,2*2采样
    layers.MaxPooling2D((2, 2)),                   
    # 设置二维卷积层2,设置64个3*3卷积核,activation参数将激活函数设置为ReLu函数
    layers.Conv2D(64, (3, 3), activation='relu'),  
    #池化层2,2*2采样
    layers.MaxPooling2D((2, 2)),                   
    
    layers.Flatten(),                    #Flatten层,连接卷积层与全连接层
    layers.Dense(64, activation='relu'), #全连接层,特征进一步提取,64为输出空间的维数,activation参数将激活函数设置为ReLu函数
    layers.Dense(10)                     #输出层,输出预期结果,10为输出空间的维数
])
# 打印网络结构
model.summary()
num_classes = 4

"""
关于卷积核的计算不懂的可以参考文章:https://blog.csdn.net/qq_38251616/article/details/114278995

layers.Dropout(0.4) 作用是防止过拟合,提高模型的泛化能力。
在上一篇文章花朵识别中,训练准确率与验证准确率相差巨大就是由于模型过拟合导致的

关于Dropout层的更多介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/115826689
"""

model = models.Sequential([
    layers.experimental.preprocessing.Rescaling(1./255, input_shape=(img_height, img_width, 3)),
    
    layers.Conv2D(16, (3, 3), activation='relu', input_shape=(img_height, img_width, 3)), # 卷积层1,卷积核3*3  
    layers.AveragePooling2D((2, 2)),               # 池化层1,2*2采样
    layers.Conv2D(32, (3, 3), activation='relu'),  # 卷积层2,卷积核3*3
    layers.AveragePooling2D((2, 2)),               # 池化层2,2*2采样
    layers.Conv2D(64, (3, 3), activation='relu'),  # 卷积层3,卷积核3*3
    layers.Dropout(0.3),  
    
    layers.Flatten(),                       # Flatten层,连接卷积层与全连接层
    layers.Dense(128, activation='relu'),   # 全连接层,特征进一步提取
    layers.Dense(num_classes)               # 输出层,输出预期结果
])

model.summary()  # 打印网络结构
model = models.Sequential([
             layers.Conv2D(16,(3,3),padding='same',activation='relu',input_shape=((img_height,img_width,3),kernel_regularizer=regularizers.l2(0.001)),
             layers.AveragePooling2D((2.2)),
             layers.BatchNormalization(),

             layers.Conv2D(32,(3,3),padding='same',activation='relu',kernel_regularizer=regularizers.l2(0.001))
             layers.AveragePooling2D((2.2)),
             layers.BatchNormalization(),
             
             layers.Conv2D(64,(3,3),padding='same',activation='relu',kernel_regularizer=regularizers.l2(0.001))
             layers.AveragePooling2D((2.2)),
             layers.BatchNormalization(),
             layers.Dropout(0.3),
            
             layers.Flatten(),
             layers.Dense(128,activation='relu'),
             layers.Dense(num_classes)
])
    
model.summary()

7、编译模型

在准备对模型进行训练之前,还需要再对其进行一些设置。以下内容是在模型的编译步骤中添加的:

损失函数(loss):用于衡量模型在训练期间的准确率。
优化器(optimizer):决定模型如何根据其看到的数据和自身的损失函数进行更新。
指标(metrics):用于监控训练和测试步骤。以下示例使用了准确率,即被正确分类的图像的比率。

"""
这里设置优化器、损失函数以及metrics
这三者具体介绍可参考我的博客:
https://blog.csdn.net/qq_38251616/category_10258234.html
"""
# model.compile()方法用于在配置训练方法时,告知训练时用的优化器、损失函数和准确率评测标准
model.compile(
	# 设置优化器为Adam优化器
    optimizer='adam',
	# 设置损失函数为交叉熵损失函数(tf.keras.losses.SparseCategoricalCrossentropy())
    # from_logits为True时,会将y_pred转化为概率(用softmax),否则不进行转换,通常情况下用True结果更稳定
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    # 设置性能指标列表,将在模型训练时监控列表中的指标
    metrics=['accuracy'])
# 设置优化器
opt = tf.keras.optimizers.Adam(learning_rate=0.001)

model.compile(optimizer=opt,
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

8、训练模型

history = model.fit()

train_ds

validation_data

epochs

"""
这里设置输入训练数据集(图片及标签)、验证数据集(图片及标签)以及迭代次数epochs
关于model.fit()函数的具体介绍可参考我的博客:
https://blog.csdn.net/qq_38251616/category_10258234.html
"""
history = model.fit(
    # 输入训练集图片
	train_images, 
	# 输入训练集标签
	train_labels, 
	# 设置10个epoch,每一个epoch都将会把所有的数据输入模型完成一次训练。
	epochs=10, 
	# 设置验证集
    validation_data=(test_images, test_labels))
epochs = 10

history = model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=epochs
)

9、预测
通过模型进行预测得到的是每一个类别的概率,数字越大该图片为该类别的可能性越大

展示测试集的图片

plt.imshow(test_images[1])

输出测试集中第一张图片的预测结果

预测 pre = model.predict预测

pre = model.predict

array?

pre = model.predict(test_images) # 对所有测试图片进行预测
pre[1] # 输出第一张图片的预测结果
import numpy as np

pre = model.predict(test_images)
print(class_names[np.argmax(pre[1])])

10、模型评估

训练集和验证集的损失函数与准确值图

模型评估可视化 loss accuracy

range 可迭代对象

figsize 图像大小

dpi 像素数

acc = history.history['accuracy']
val_acc = history.history['val_accuracy']

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs_range = range(epochs)

plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值