• 365天深度学习训练营-第6周:好莱坞明星识别


    目录

    一、前言

    二、我的环境

    三、代码实现

     四、损失函数

    1. binary_crossentropy(对数损失函数)

    2. categorical_crossentropy(多分类的对数损失函数)

    3. sparse_categorical_crossentropy(稀疏性多分类的对数损失函数)

    五、VGG-16复现

    六、总结并改进

    1、VGG总结

    2、报错改正

    一、前言

    1. >- **🍨 本文为[🔗365天深度学习训练营](https://mp.weixin.qq.com/s/xLjALoOD8HPZcH563En8bQ) 中的学习记录博客**
    2. >- **🍦 参考文章:365天深度学习训练营-第6周:好莱坞明星识别(训练营内部成员可读)**
    3. >- **🍖 原作者:[K同学啊|接辅导、项目定制](https://mtyjkh.blog.csdn.net/)**
    1. ● 难度:夯实基础
    2. ● 语言:Python3、TensorFlow2
    3. ● 时间:829-92
    4. 🍺 要求:
    5. 1. 使用categorical_crossentropy(多分类的对数损失函数)完成本次选题
    6. 2. 探究不同损失函数的使用场景与代码实现
    7. 🍻 拔高(可选):
    8. 1. 自己搭建VGG-16网络框架
    9. 2. 调用官方的VGG-16网络框架
    10. 3. 使用VGG-16算法训练该模型
    11. 🔎 探索(难度有点大)
    12. 1. 准确率达到60%

    二、我的环境

    语言环境:Python3.7

    编译器:jupyter notebook

    深度学习环境:TensorFlow2

    三、代码实现

    1. from tensorflow import keras
    2. from tensorflow.keras import layers, models
    3. import os, PIL, pathlib
    4. import matplotlib.pyplot as plt
    5. import tensorflow as tf
    6. import numpy as np
    7. gpus = tf.config.list_physical_devices("GPU")
    8. if gpus:
    9. gpu0 = gpus[0] # 如果有多个GPU,仅使用第0个GPU
    10. tf.config.experimental.set_memory_growth(gpu0, True) # 设置GPU显存用量按需使用
    11. tf.config.set_visible_devices([gpu0], "GPU")
    12. gpus
    13. data_dir = "./48-data/"
    14. data_dir = pathlib.Path(data_dir)
    15. image_count = len(list(data_dir.glob('*/*.jpg')))
    16. print("图片总数为:", image_count)
    17. roses = list(data_dir.glob('Jennifer Lawrence/*.jpg'))
    18. PIL.Image.open(str(roses[0]))
    19. batch_size = 32
    20. img_height = 224
    21. img_width = 224
    22. """
    23. 关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
    24. """
    25. train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    26. data_dir,
    27. validation_split=0.1,
    28. subset="training",
    29. label_mode="categorical",
    30. seed=123,
    31. image_size=(img_height, img_width),
    32. batch_size=batch_size)
    33. """
    34. 关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
    35. """
    36. val_ds = tf.keras.preprocessing.image_dataset_from_directory(
    37. data_dir,
    38. validation_split=0.1,
    39. subset="validation",
    40. label_mode="categorical",
    41. seed=123,
    42. image_size=(img_height, img_width),
    43. batch_size=batch_size)
    44. class_names = train_ds.class_names
    45. print(class_names)
    46. plt.figure(figsize=(20, 10))
    47. for images, labels in train_ds.take(1):
    48. for i in range(20):
    49. ax = plt.subplot(5, 10, i + 1)
    50. plt.imshow(images[i].numpy().astype("uint8"))
    51. plt.title(class_names[np.argmax(labels[i])])
    52. plt.axis("off")
    53. for image_batch, labels_batch in train_ds:
    54. print(image_batch.shape)
    55. print(labels_batch.shape)
    56. break
    57. AUTOTUNE = tf.data.AUTOTUNE
    58. train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
    59. val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
    60. """
    61. 关于卷积核的计算不懂的可以参考文章:https://blog.csdn.net/qq_38251616/article/details/114278995
    62. layers.Dropout(0.4) 作用是防止过拟合,提高模型的泛化能力。
    63. 关于Dropout层的更多介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/115826689
    64. """
    65. model = models.Sequential([
    66. layers.experimental.preprocessing.Rescaling(1. / 255, input_shape=(img_height, img_width, 3)),
    67. layers.Conv2D(16, (3, 3), activation='relu', input_shape=(img_height, img_width, 3)), # 卷积层1,卷积核3*3
    68. layers.AveragePooling2D((2, 2)), # 池化层1,2*2采样
    69. layers.Conv2D(32, (3, 3), activation='relu'), # 卷积层2,卷积核3*3
    70. layers.AveragePooling2D((2, 2)), # 池化层2,2*2采样
    71. layers.Dropout(0.5),
    72. layers.Conv2D(64, (3, 3), activation='relu'), # 卷积层3,卷积核3*3
    73. layers.AveragePooling2D((2, 2)),
    74. layers.Dropout(0.5),
    75. layers.Conv2D(128, (3, 3), activation='relu'), # 卷积层3,卷积核3*3
    76. layers.Dropout(0.5),
    77. layers.Flatten(), # Flatten层,连接卷积层与全连接层
    78. layers.Dense(128, activation='relu'), # 全连接层,特征进一步提取
    79. layers.Dense(len(class_names)) # 输出层,输出预期结果
    80. ])
    81. model.summary() # 打印网络结构
    82. # 设置初始学习率
    83. initial_learning_rate = 1e-4
    84. lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
    85. initial_learning_rate,
    86. decay_steps=60, # 敲黑板!!!这里是指 steps,不是指epochs
    87. decay_rate=0.96, # lr经过一次衰减就会变成 decay_rate*lr
    88. staircase=True)
    89. # 将指数衰减学习率送入优化器
    90. optimizer = tf.keras.optimizers.Adam(learning_rate=lr_schedule)
    91. model.compile(optimizer=optimizer,
    92. loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
    93. metrics=['accuracy'])
    94. from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping
    95. epochs = 100
    96. # 保存最佳模型参数
    97. checkpointer = ModelCheckpoint('best_model.h5',
    98. monitor='val_accuracy',
    99. verbose=1,
    100. save_best_only=True,
    101. save_weights_only=True)
    102. # 设置早停
    103. earlystopper = EarlyStopping(monitor='val_accuracy',
    104. min_delta=0.001,
    105. patience=20,
    106. verbose=1)
    107. history = model.fit(train_ds,
    108. validation_data=val_ds,
    109. epochs=epochs,
    110. callbacks=[checkpointer, earlystopper])
    111. acc = history.history['accuracy']
    112. val_acc = history.history['val_accuracy']
    113. loss = history.history['loss']
    114. val_loss = history.history['val_loss']
    115. epochs_range = range(len(loss))
    116. plt.figure(figsize=(12, 4))
    117. plt.subplot(1, 2, 1)
    118. plt.plot(epochs_range, acc, label='Training Accuracy')
    119. plt.plot(epochs_range, val_acc, label='Validation Accuracy')
    120. plt.legend(loc='lower right')
    121. plt.title('Training and Validation Accuracy')
    122. plt.subplot(1, 2, 2)
    123. plt.plot(epochs_range, loss, label='Training Loss')
    124. plt.plot(epochs_range, val_loss, label='Validation Loss')
    125. plt.legend(loc='upper right')
    126. plt.title('Training and Validation Loss')
    127. plt.show()

     

     四、损失函数

    损失函数Loss详解:

    1. binary_crossentropy(对数损失函数)

    sigmoid 相对应的损失函数,针对于二分类问题。

    2. categorical_crossentropy(多分类的对数损失函数)

    softmax 相对应的损失函数,如果是one-hot编码,则使用 categorical_crossentropy

    调用方法一:

    1. model.compile(optimizer="adam",
    2. loss='categorical_crossentropy',
    3. metrics=['accuracy'])

    调用方法二:

    1. model.compile(optimizer="adam",
    2. loss=tf.keras.losses.CategoricalCrossentropy(),
    3. metrics=['accuracy'])

    3. sparse_categorical_crossentropy(稀疏性多分类的对数损失函数)

    softmax 相对应的损失函数,如果是整数编码,则使用 sparse_categorical_crossentropy

    调用方法一:

    1. model.compile(optimizer="adam",
    2. loss='sparse_categorical_crossentropy',
    3. metrics=['accuracy'])

    调用方法二:

    1. model.compile(optimizer="adam",
    2. loss=tf.keras.losses.SparseCategoricalCrossentropy(),
    3. metrics=['accuracy'])

    函数原型

    1. tf.keras.losses.SparseCategoricalCrossentropy(
    2. from_logits=False,
    3. reduction=losses_utils.ReductionV2.AUTO,
    4. name='sparse_categorical_crossentropy'
    5. )

    参数说明:

    • from_logits: 为True时,会将y_pred转化为概率(用softmax),否则不进行转换,通常情况下用True结果更稳定;
    • reduction:类型为tf.keras.losses.Reduction,对loss进行处理,默认是AUTO;
    • name: name

    五、VGG-16复现

    1. def VGG16(nb_classes, input_shape):
    2. input_tensor = Input(shape=input_shape)
    3. # 1st block
    4. x = Conv2D(64, (3,3), activation='relu', padding='same',name='block1_conv1')(input_tensor)
    5. x = Conv2D(64, (3,3), activation='relu', padding='same',name='block1_conv2')(x)
    6. x = MaxPooling2D((2,2), strides=(2,2), name = 'block1_pool')(x)
    7. # 2nd block
    8. x = Conv2D(128, (3,3), activation='relu', padding='same',name='block2_conv1')(x)
    9. x = Conv2D(128, (3,3), activation='relu', padding='same',name='block2_conv2')(x)
    10. x = MaxPooling2D((2,2), strides=(2,2), name = 'block2_pool')(x)
    11. # 3rd block
    12. x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv1')(x)
    13. x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv2')(x)
    14. x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv3')(x)
    15. x = MaxPooling2D((2,2), strides=(2,2), name = 'block3_pool')(x)
    16. # 4th block
    17. x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv1')(x)
    18. x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv2')(x)
    19. x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv3')(x)
    20. x = MaxPooling2D((2,2), strides=(2,2), name = 'block4_pool')(x)
    21. # 5th block
    22. x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv1')(x)
    23. x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv2')(x)
    24. x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv3')(x)
    25. x = MaxPooling2D((2,2), strides=(2,2), name = 'block5_pool')(x)
    26. # full connection
    27. x = Flatten()(x)
    28. x = Dense(4096, activation='relu', name='fc1')(x)
    29. x = Dense(4096, activation='relu', name='fc2')(x)
    30. output_tensor = Dense(nb_classes, activation='softmax', name='predictions')(x)
    31. model = Model(input_tensor, output_tensor)
    32. return model
    33. model=VGG16(len(class_names), (img_width, img_height, 3))
    34. model.summary()

    代码实现:

    1. from tensorflow import keras
    2. from tensorflow.keras import layers, models
    3. import os, PIL, pathlib
    4. import matplotlib.pyplot as plt
    5. import tensorflow as tf
    6. import numpy as np
    7. gpus = tf.config.list_physical_devices("GPU")
    8. if gpus:
    9. gpu0 = gpus[0] # 如果有多个GPU,仅使用第0个GPU
    10. tf.config.experimental.set_memory_growth(gpu0, True) # 设置GPU显存用量按需使用
    11. tf.config.set_visible_devices([gpu0], "GPU")
    12. gpus
    13. data_dir = "./48-data/"
    14. data_dir = pathlib.Path(data_dir)
    15. image_count = len(list(data_dir.glob('*/*.jpg')))
    16. print("图片总数为:",image_count)
    17. batch_size = 32
    18. img_height = 224
    19. img_width = 224
    20. """
    21. 关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
    22. """
    23. train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    24. data_dir,
    25. validation_split=0.2,
    26. subset="training",
    27. seed=123,
    28. image_size=(img_height, img_width),
    29. batch_size=batch_size)
    30. """
    31. 关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
    32. """
    33. val_ds = tf.keras.preprocessing.image_dataset_from_directory(
    34. data_dir,
    35. validation_split=0.2,
    36. subset="validation",
    37. seed=123,
    38. image_size=(img_height, img_width),
    39. batch_size=batch_size)
    40. class_names = train_ds.class_names
    41. print(class_names)
    42. plt.figure(figsize=(10, 4)) # 图形的宽为10高为5
    43. for images, labels in train_ds.take(1):
    44. for i in range(10):
    45. ax = plt.subplot(2, 5, i + 1)
    46. plt.imshow(images[i].numpy().astype("uint8"))
    47. plt.title(class_names[labels[i]])
    48. plt.axis("off")
    49. for image_batch, labels_batch in train_ds:
    50. print(image_batch.shape)
    51. print(labels_batch.shape)
    52. break
    53. AUTOTUNE = tf.data.AUTOTUNE
    54. train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
    55. val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
    56. normalization_layer = layers.experimental.preprocessing.Rescaling(1./255)
    57. train_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
    58. val_ds = val_ds.map(lambda x, y: (normalization_layer(x), y))
    59. image_batch, labels_batch = next(iter(val_ds))
    60. first_image = image_batch[0]
    61. # 查看归一化后的数据
    62. print(np.min(first_image), np.max(first_image))
    63. from tensorflow.keras import layers, models, Input
    64. from tensorflow.keras.models import Model
    65. from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout
    66. def VGG16(nb_classes, input_shape):
    67. input_tensor = Input(shape=input_shape)
    68. # 1st block
    69. x = Conv2D(64, (3,3), activation='relu', padding='same',name='block1_conv1')(input_tensor)
    70. x = Conv2D(64, (3,3), activation='relu', padding='same',name='block1_conv2')(x)
    71. x = MaxPooling2D((2,2), strides=(2,2), name = 'block1_pool')(x)
    72. # 2nd block
    73. x = Conv2D(128, (3,3), activation='relu', padding='same',name='block2_conv1')(x)
    74. x = Conv2D(128, (3,3), activation='relu', padding='same',name='block2_conv2')(x)
    75. x = MaxPooling2D((2,2), strides=(2,2), name = 'block2_pool')(x)
    76. # 3rd block
    77. x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv1')(x)
    78. x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv2')(x)
    79. x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv3')(x)
    80. x = MaxPooling2D((2,2), strides=(2,2), name = 'block3_pool')(x)
    81. # 4th block
    82. x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv1')(x)
    83. x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv2')(x)
    84. x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv3')(x)
    85. x = MaxPooling2D((2,2), strides=(2,2), name = 'block4_pool')(x)
    86. # 5th block
    87. x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv1')(x)
    88. x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv2')(x)
    89. x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv3')(x)
    90. x = MaxPooling2D((2,2), strides=(2,2), name = 'block5_pool')(x)
    91. # full connection
    92. x = Flatten()(x)
    93. x = Dense(4096, activation='relu', name='fc1')(x)
    94. x = Dense(4096, activation='relu', name='fc2')(x)
    95. output_tensor = Dense(nb_classes, activation='softmax', name='predictions')(x)
    96. model = Model(input_tensor, output_tensor)
    97. return model
    98. model=VGG16(len(class_names), (img_width, img_height, 3))
    99. model.summary()
    100. # 设置初始学习率
    101. initial_learning_rate = 1e-4
    102. lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
    103. initial_learning_rate,
    104. decay_steps=30, # 敲黑板!!!这里是指 steps,不是指epochs
    105. decay_rate=0.92, # lr经过一次衰减就会变成 decay_rate*lr
    106. staircase=True)
    107. # 设置优化器
    108. opt = tf.keras.optimizers.Adam(learning_rate=initial_learning_rate)
    109. model.compile(optimizer=opt,
    110. loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    111. metrics=['accuracy'])
    112. epochs = 20
    113. history = model.fit(
    114. train_ds,
    115. validation_data=val_ds,
    116. epochs=epochs
    117. )
    118. acc = history.history['accuracy']
    119. val_acc = history.history['val_accuracy']
    120. loss = history.history['loss']
    121. val_loss = history.history['val_loss']
    122. epochs_range = range(epochs)
    123. plt.figure(figsize=(12, 4))
    124. plt.subplot(1, 2, 1)
    125. plt.plot(epochs_range, acc, label='Training Accuracy')
    126. plt.plot(epochs_range, val_acc, label='Validation Accuracy')
    127. plt.legend(loc='lower right')
    128. plt.title('Training and Validation Accuracy')
    129. plt.subplot(1, 2, 2)
    130. plt.plot(epochs_range, loss, label='Training Loss')
    131. plt.plot(epochs_range, val_loss, label='Validation Loss')
    132. plt.legend(loc='upper right')
    133. plt.title('Training and Validation Loss')
    134. plt.show()

    六、总结并改进

    1、VGG总结

    用VGG-16代码效果不是很理想,与CNN的结果相似,在查阅资料以后改进方法如下

    2、报错改正

    原vgg是10分类 我们需要检测的是17类 所以需要再最后的全连接层改为17

     内存不够,可以将batch_size 调小 重新进行训练

     

  • 相关阅读:
    面向对象设计模式
    基于.net C# Socket WinForm MQTT 客户端开发
    Spring Cloud Gateway系列【5】GatewayFilter网关过滤器详解
    基于Stable Diffusion的图像合成数据集
    kubernetes 生成认证文件
    C语言中文网 - Shell脚本 - 5
    计算机毕设(附源码)JAVA-SSM基于协同过滤技术的旅游景点购票系统
    IDL学习:语法基础-程序控制
    C++语法篇(一)
    Spring中加密工具类DigestUtils和BCryptPasswordEncoder
  • 原文地址:https://blog.csdn.net/m0_58585940/article/details/127910988