对服装图像进行分类-基于tensorflow

导入 Fashion MNIST 数据集

该数据集包含 10 个类别的 70,000 个灰度图像。这些图像以低分辨率(28x28 像素)展示了单件衣物

我们将使用 60,000 张图像来训练网络,使用 10,000 张图像来评估网络学习对图像进行分类的准确程度。可以直接从 TensorFlow 中访问 Fashion MNIST。直接从 TensorFlow 中导入和加载 Fashion MNIST 数据:

import tensorflow as tf
fashion_mnist = tf.keras.datasets.fashion_mnist

(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

加载数据集会返回四个 NumPy 数组:

  • train_images 和 train_labels 数组是训练集,即模型用于学习的数据。
  • 测试集test_images 和 test_labels 数组会被用来对模型进行测试。

图像是 28x28 的 NumPy 数组,像素值介于 0 到 255 之间。标签是整数数组,介于 0 到 9 之间。这些标签对应于图像所代表的服装

标签
0T恤/上衣
1裤子
2套头衫
3连衣裙
4外套
5凉鞋
6衬衫
7运动鞋
8
9短靴

每个图像都会被映射到一个标签。由于数据集不包括类名称,请将它们存储在下方,供稍后绘制图像时使用:

class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

数据预处理

将这些值缩小至 0 到 1 之间,然后将其馈送到神经网络模型。为此,请将这些值除以 255。

train_images = train_images / 255.0

test_images = test_images / 255.0

搭建模型

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(units=128, activation='relu'),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(units=10)
]
)//注意这个结构是再列表中的。

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
model.fit(train_images,train_labels,epochs=10,verbose=2)
print('\nTest accuracy:', test_acc)

Epoch 1/10
1875/1875 - 1s - loss: 0.5296 - accuracy: 0.8119
Epoch 2/10
1875/1875 - 1s - loss: 0.3999 - accuracy: 0.8551
Epoch 3/10
1875/1875 - 1s - loss: 0.3669 - accuracy: 0.8666
Epoch 4/10
1875/1875 - 1s - loss: 0.3422 - accuracy: 0.8753
Epoch 5/10
1875/1875 - 1s - loss: 0.3298 - accuracy: 0.8786
Epoch 6/10
1875/1875 - 1s - loss: 0.3159 - accuracy: 0.8824
Epoch 7/10
1875/1875 - 1s - loss: 0.3059 - accuracy: 0.8868
Epoch 8/10
1875/1875 - 1s - loss: 0.2982 - accuracy: 0.8893
Epoch 9/10
1875/1875 - 1s - loss: 0.2878 - accuracy: 0.8922
Epoch 10/10
RuntimeError: module compiled against API version 0xe but this version of numpy is 0xd
RuntimeError: module compiled against API version 0xe but this version of numpy is 0xd
RuntimeError: module compiled against API version 0xe but this version of numpy is 0xd
1875/1875 - 1s - loss: 0.2815 - accuracy: 0.8943
313/313 - 0s - loss: 0.3346 - accuracy: 0.8813

Test accuracy: 0.8812999725341797

进行预测

模型经过训练后,可以使用它对一些图像进行预测。附加一个 Softmax 层,将模型的线性输出 logits 转换成更容易理解的概率。

probability_model = tf.keras.Sequential([model, tf.keras.layers.Softmax()])
predictions = probability_model.predict(test_images)

原理

假设有一个深度学习的图像识别任务,目标是将图像分类为不同的类别。在这个任务中,使用了一个预训练的卷积神经网络模型(CNN),该模型是全球图像识别挑战赛(ImageNet)的冠军模型,被称为“InceptionNet”。

在一个新的图像数据集上训练了此模型,并在训练完成后对其进行了评估。随后,想要使用这个模型对新来的测试图像进行识别。

问题点:
可能会发现原始模型的输出不是概率,而是一些未归一化的分数,通常被称为 logits。为了使得模型的输出易读(比如,可以直接用最大概率来做决策),需要将这些分数转换为概率分布。

解决方案:
可以使用 tf.keras.layers.Softmax() 层来将模型的输出转换为概率分布。当调用 model.predict() 时,模型会输出一个分数矩阵(一个形状为 (batch_size, num_classes) 的数组),这些分数是模型对于每一个图像类别输出的分数。但是这些分数并不是概率。

这里是如何应用 Softmax 层:

# 首先假设 model 是你的预训练模型
original_model_output = model.predict(test_images)

# 查看 original_model_output 的形状,应该是 (batch_size, num_classes)
print("Original model output shape:", original_model_output.shape)

# 将 Softmax 层添加到 Sequential 模型中,以创建一个新的概率模型
probability_model = tf.keras.Sequential([
    model,
    tf.keras.layers.Softmax()
])

# 使用新的模型进行预测
probability_model_output = probability_model.predict(test_images)

# 查看新的概率模型的输出形状,应该是 (batch_size, num_classes)
print("Probability model output shape:", probability_model_output.shape)

在这个场景中,probability_model_output 现在是一个概率分布,每个元素的值加起来等于1,你可以直接用来做决策。例如,你可以通过查找最大概率来预测一个图像的类别:

# 获取最大概率的类别
predicted_class = np.argmax(probability_model_output, axis=1)

总结:
在这个场景中,我们通过在最有可能已经训练好的模型后面增加一个 Softmax 层,创建了一个新的 probability_model。这个新的模型可以直接用来进行新的图像识别任务,而不需要重新编译,因为在预测过程中并不需要了解模型的训练设置(如损失函数、优化器等)。这使得 probability_model 非常适合实际应用中快速预测新的数据。

注意:只是用Softmax计算概率不需要重新编译。

在深度学习和机器学习中,(batch_size, num_classes) 是表示模型输出的数组(张量)的形状。这里是对这两个维度的详细解释:

1. batch_size(批次大小)

  • 定义batch_size 表示每次训练或预测时输入数据的样本数量。一个批次包含的样本数即为批次大小。
  • 作用:在训练过程中,深度学习模型通常不会一次处理所有训练样本,而是将数据分成多个批次进行处理。这样做的好处包括减少内存使用和加快训练速度。批次大小通常是一个可以调节的超参数,取决于硬件资源和模型的需要。
  • 举例:如果有一个数据集包含 1000 张图像,并且设置 batch_size=32,那么每次训练时,模型将处理 32 张图像作为一个批次。

2. num_classes(类别数)

  • 定义num_classes 表示模型的输出类别数,即模型可以预测的不同类别的数量。这通常对应于分类任务中的目标类别。
  • 作用:在分类任务中,模型的最终输出层通常有 num_classes 个神经元,每个神经元输出一个类别的分数或概率。通过这些分数或概率,模型可以预测输入样本的类别。
  • 举例:如果在进行手写数字识别任务(例如 MNIST 数据集),你会有 10 个类别(数字 0 到 9),因此 num_classes 将是 10。

输出形状示例

假设你在进行图像分类任务,模型的输出是一个形状为 (batch_size, num_classes) 的数组。下面是对这一形状的具体解释:

  • 预测的输出:每一行代表一个样本的分类分数或概率。每一列代表一个类别的分数或概率。

    • 如果 batch_size=32 和 num_classes=10,那么模型的输出形状将是 (32, 10)
    • 这表示模型一次处理 32 张图像,并为每张图像预测 10 个类别中的每一个的分数或概率。

实际应用示例

假设你用一个模型进行预测:

# 假设模型的输出
output = model.predict(test_images)

# 输出形状为 (batch_size, num_classes)
print("Output shape:", output.shape)

如果 test_images 的 batch_size 为 64,且模型有 5 个类别,那么 output.shape 将是 (64, 5)。这意味着模型为 64 张图像生成了 64 行输出,每行有 5 个类别的分数或概率。

总结

  • batch_size:每次处理的样本数量。
  • num_classes:模型可以预测的不同类别的数量。

是否需要重新编译

假设使用一个预训练好的模型进行了微调训练(fine-tuning),并且现在希望重新编译概率模型以进行另一个评估步骤。下面是一个例子:

import tensorflow as tf
from tensorflow.keras.applications import InceptionV3

# 假设有一个数据集名为 "data",它包含了 "x_train", "y_train", "x_test", 和 "y_test"

# 定义原始模型
base_model = InceptionV3(include_top=False, input_shape=(299, 299, 3), weights='imagenet')

# 冻结住InceptionV3模型的权重以进行微调训练
for layer in base_model.layers:
    layer.trainable = False

# 在模型后添加自定义层
# 这里我们使用 Dense 层和 Softmax 层
top_model = tf.keras.Sequential([
    tf.keras.layers.GlobalAveragePooling2D(input_shape=base_model.output_shape[1:]),
    tf.keras.layers.Dense(512, activation='relu'),
    tf.keras.layers.Dropout(0.5),
    tf.keras.layers.Dense(2, activation='softmax')  # 假设数据集有两个类别
])

# 创建一个完全的新模型,它包括所有已有层
# 假设已经对 "base_model" 完成了微调训练
# 现在需要重新编译概率模型以进行评估

probability_model = tf.keras.Sequential([
    base_model,
    top_model
])

# 重新编译模型
probability_model.compile(optimizer='adam',
                          loss='sparse_categorical_crossentropy',
                          metrics=['accuracy'])

# 进行评估
eval_results = probability_model.evaluate(x_test, y_test, verbose=2)
print(f'Test accuracy: {eval_results[1]*100:.2f}%')

在这个例子中,我们首先加载了一个预训练的 InceptionV3 模型,然后冻结了所有层以进行微调训练。之后,我们在模型上添加了一个自定义的顶层模型。因为我们之前对 base_model 进行了训练和编译,我们在添加 Softmax 层之后决定重新编译整个模型以进行评估。

在这种情况下,compile 方法是必须的,因为我们需要在新的层上指定优化器、损失函数和评估指标。如果不重新编译,权重将不会在评估中得到更新,而且如果我们改变了损失函数或者评估指标,则无法获得正确的评估结果。

请注意,上面的代码片段假设了你已经有了一个训练好的 base_model。在这个示例中,我们通过 tf.keras.Sequential 创建了 probability_model,它包含了完整的 base_model 和顶部的新自定义层。通过重新编译 probability_model,我们可以使用新的评估指标和损失函数,并在新的层上应用优化器。

编译和训练的区别

在深度学习中,model.compile 和 model.fit 是两个重要的步骤,它们在模型的训练和评估中各自扮演着不同的角色。下面是对这两个方法的详细解释,以及它们在实际应用中的区别和作用。

model.compile

作用model.compile 用于配置模型的学习过程,它设置了训练模型时所需的优化器、损失函数和评估指标。这一步骤必须在训练之前完成,因为它指定了如何优化模型的权重以及如何评估模型的表现。

参数

  • optimizer:指定用于优化模型的算法。例如,'adam''sgd'(随机梯度下降)等。
  • loss:定义模型的损失函数,用于衡量模型预测值与实际值之间的差距。例如,'sparse_categorical_crossentropy'(适用于分类任务)或 mse(均方误差,适用于回归任务)。
  • metrics:用于评估模型性能的指标。例如,'accuracy''precision' 等。

情景示例

假设在做图像分类任务,有一个卷积神经网络(CNN),已经定义好了模型结构。接下来,需要配置模型以准备好进行训练。需要选择优化器、损失函数和评估指标。这时候,会调用 model.compile

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

这段代码完成了模型配置:

  • 优化器'adam' 是一种常用的自适应学习率优化器。
  • 损失函数'sparse_categorical_crossentropy' 适用于多类别分类问题,其中标签是整数编码。
  • 评估指标'accuracy' 用于计算分类准确率。

model.fit

作用model.fit 用于实际训练模型,它将输入数据(特征和标签)喂给模型,并通过最小化损失函数来更新模型的权重。这个过程涉及多次遍历训练数据(称为 epochs),每次遍历更新模型的权重,以逐步优化模型的表现。

参数

  • x:训练数据的特征(输入)。
  • y:训练数据的标签(目标)。
  • epochs:训练的轮数,即模型遍历整个训练数据集的次数。
  • batch_size:每次训练时使用的样本数,决定了模型每次权重更新的频率。
  • validation_data:用于验证模型性能的数据集(可选)。

情景示例

在配置好模型之后,可以使用 model.fit 进行训练。这一步将数据输入到模型中并优化模型的权重。假设有训练数据 x_train 和标签 y_train,并且希望训练 10 个 epochs,会这样做:

history = model.fit(x_train, y_train,
                    epochs=10,
                    batch_size=32,
                    validation_data=(x_val, y_val))

这段代码将:

  • 训练数据x_train 和 y_train 是模型的输入数据和目标标签。
  • epochs:指定训练轮数为 10 次。
  • batch_size:每次训练使用 32 个样本。
  • validation_data:提供一个验证数据集 x_val 和 y_val,用于在每个 epoch 结束时评估模型的性能,帮助监控模型的泛化能力。

总结

  • model.compile

    • 作用:配置模型的学习过程。
    • 何时使用:在训练模型之前,设置优化器、损失函数和评估指标。
  • model.fit

    • 作用:实际训练模型,更新模型的权重。
    • 何时使用:在模型配置好后,用于训练模型并优化权重。

Sequential

在 TensorFlow 中,可以通过在模型后面加一个 Softmax 层来创建一个概率模型,这样可以将模型的输出转换为概率分布。使用 tf.keras.Sequential 创建包含 Softmax 层的概率模型是一种常见的做法,但需要注意几个事项:

1. 模型结构和输出

  • 模型输出:原始模型的输出是 logits(未归一化的得分),即没有经过 softmax 处理的原始分数。
  • Softmax 层:将 logits 转换为概率分布。如果模型最后的输出层已经是 softmax,那么在其后再加一个 softmax 层就没有必要,因为这样可能会导致数值不稳定或者不必要的计算开销。

2. 代码示例

假设有一个已经训练好的模型 model,并且这个模型的输出是 logits。可以这样创建一个概率模型:

import tensorflow as tf

# 假设 model 是训练好的模型
# 创建一个新模型,在原有模型后添加 Softmax 层
probability_model = tf.keras.Sequential([
    model,
    tf.keras.layers.Softmax()
])

# 编译新的模型
probability_model.compile(optimizer='adam',
                          loss='sparse_categorical_crossentropy',
                          metrics=['accuracy'])

3. 注意事项

  1. 输出层是否已经包含 Softmax: 确保原始模型的最后一层不是 softmax。如果原始模型的最后一层是 softmax,那么加一个 softmax 层将导致重复计算,结果不正确。

  2. 使用 model 的 .predict() 方法: 如果已经有一个训练好的模型 model,可以直接使用 model.predict() 来得到概率分布(前提是原始模型的最后一层是 softmax 或类似的激活函数)。

    # 使用原始模型进行预测
    predictions = model.predict(x_test)  # 这里的 predictions 已经是概率分布
    
  3. 训练和评估: 如果想要对 probability_model 进行训练或评估,确保数据格式和标签与模型的要求一致。

4. 实际应用

示例:在使用 model 作为特征提取器时

# 假设原始模型用于提取特征
feature_extractor = tf.keras.Model(inputs=model.input, outputs=model.output)

# 在特征提取器后添加 Softmax 层
probability_model = tf.keras.Sequential([
    feature_extractor,
    tf.keras.layers.Softmax()
])

# 现在可以使用 probability_model 进行预测
predictions = probability_model.predict(x_test)

总结来说,在模型的后面加一个 Softmax 层可以实现将 logits 转换为概率分布,但要确保原始模型的输出是未归一化的 logits,并且原始模型的最后一层没有使用 softmax。如果原始模型已经包含 softmax,则直接使用原始模型的输出即可。

全部代码

import tensorflow as tf
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt

fashion_mnist = tf.keras.datasets.fashion_mnist

(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
train_images = train_images / 255.0

test_images = test_images / 255.0

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(units=128, activation='relu'),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(units=10)
]
)

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
model.fit(train_images,train_labels,epochs=10,verbose=2)
test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)

probability_model = tf.keras.Sequential([model,tf.keras.layers.Softmax()])
predictions = probability_model.predict(test_images)
def plot_image(i, predictions_array, true_label, img):
  true_label, img = true_label[i], img[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])

  plt.imshow(img, cmap=plt.cm.binary)

  predicted_label = np.argmax(predictions_array)
  if predicted_label == true_label:
    color = 'blue'
  else:
    color = 'red'

  plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                100*np.max(predictions_array),
                                class_names[true_label]),
                                color=color)

def plot_value_array(i, predictions_array, true_label):
  true_label = true_label[i]
  plt.grid(False)
  plt.xticks(range(10))
  plt.yticks([])
  thisplot = plt.bar(range(10), predictions_array, color="#777777")
  plt.ylim([0, 1])
  predicted_label = np.argmax(predictions_array)

  thisplot[predicted_label].set_color('red')
  thisplot[true_label].set_color('blue')


i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i],  test_labels)
plt.show()

i = 12
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i],  test_labels)
plt.show()


num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
  plt.subplot(num_rows, 2*num_cols, 2*i+1)
  plot_image(i, predictions[i], test_labels, test_images)
  plt.subplot(num_rows, 2*num_cols, 2*i+2)
  plot_value_array(i, predictions[i], test_labels)
plt.tight_layout()
plt.show()

  • 12
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
花卉识别是计算机视觉中的一个重要应用,可以通过图像识别技术自动识别图像中的花卉种类。下面是一个基于TensorFlow 2.3实现的花卉识别程序示例。 首先,我们需要准备好训练数据和测试数据。可以使用公开的花卉数据集,例如Oxford 102花卉数据集。这个数据集包含了102种不同的花卉,每种花卉有大约80张图片。可以通过以下链接下载数据集: http://www.robots.ox.ac.uk/~vgg/data/flowers/102/index.html 下载完成后,我们需要将数据集进行处理,将其转换为模型可以处理的形式。可以使用Python中的PIL库进行图片处理,并使用TensorFlow中的ImageDataGenerator类来进行数据增强和批量处理。 ```python import tensorflow as tf from tensorflow.keras.preprocessing.image import ImageDataGenerator # 定义数据增强和预处理函数 train_datagen = ImageDataGenerator( rescale=1./255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True) test_datagen = ImageDataGenerator(rescale=1./255) # 加载训练数据和测试数据 train_data = train_datagen.flow_from_directory( 'flower_dataset/train', target_size=(224, 224), batch_size=32, class_mode='categorical') test_data = test_datagen.flow_from_directory( 'flower_dataset/test', target_size=(224, 224), batch_size=32, class_mode='categorical') ``` 接下来,我们可以定义一个卷积神经网络模型来训练我们的数据。可以使用TensorFlow中的Keras API来定义模型。 ```python from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout # 定义一个卷积神经网络模型 model = Sequential() model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(224, 224, 3))) model.add(MaxPooling2D((2, 2))) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D((2, 2))) model.add(Conv2D(128, (3, 3), activation='relu')) model.add(MaxPooling2D((2, 2))) model.add(Conv2D(128, (3, 3), activation='relu')) model.add(MaxPooling2D((2, 2))) model.add(Flatten()) model.add(Dense(512, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(102, activation='softmax')) # 编译模型 model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) ``` 定义好模型后,我们可以使用fit()方法来训练模型。可以指定训练数据和测试数据,以及一些训练参数,例如批量大小、迭代次数等。 ```python # 训练模型 history = model.fit( train_data, steps_per_epoch=100, epochs=30, validation_data=test_data, validation_steps=50) ``` 训练完成后,我们可以使用模型来进行预测。可以使用predict()方法来对单个图片进行识别,或者使用evaluate()方法来对测试集进行整体评估。 ```python # 对单个图片进行预测 import numpy as np from tensorflow.keras.preprocessing import image img_path = 'flower_dataset/test/daisy/5547758_eea9edfd54_n.jpg' img = image.load_img(img_path, target_size=(224, 224)) x = image.img_to_array(img) x = np.expand_dims(x, axis=0) x /= 255. preds = model.predict(x) print(preds) # 对测试集进行评估 test_loss, test_acc = model.evaluate(test_data, steps=50) print('Test accuracy:', test_acc) ``` 以上就是一个基于TensorFlow 2.3的花卉识别程序示例。需要注意的是,这个程序只是一个简单的示例,实际应用中可能需要进行更多的调参和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

背水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值