通过 Tensorflow 的基础类,构建卷积神经网络,用于花朵图片的分类

实验目的

通过 Tensorflow 的基础类,构建卷积神经网络,用于花朵图片的分类。

实验环境

import tensorflow as tf

print(tf.__version__)

output:
2.3.0

实验步骤

(一) 数据获取和预处理

1.1 数据选择 TensorFlow 官方提供的花朵图片数据,经如下代码获取:

dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"
img_dir= tf.keras.utils.get_file('flower_photos', origin=dataset_url, untar=True)

1.2 读取图片:这里,我们通过 tf.keras.preprocessing.image_dataset_from_directory 函数批量读入图片。

import pathlib
# 数据保存路径
data_dir = pathlib.Path(data_dir)

BATCH_SIZE = 32  # BATCH size 设为32
img_height = 180  # 读取图片后,高度转换为180像素
img_width = 180  # 读取图片后,宽度转换为180像素

# 读入images (training data)
train_ds = tf.keras.preprocessing.image_dataset_from_directory(img_dir,
                                                               shuffle=True, 
                                                               validation_split=0.2, 
                                                               seed=123, 
                                                               subset='training', 
                                                               batch_size=BATCH_SIZE,
                                                               image_size=(img_height, img_width)
                                                              )

# 读入images(test data)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(img_dir, 
                                                             shuffle=True,
                                                             validation_split=0.2,
                                                             seed=123,
                                                             subset='validation',
                                                             image_size=(img_height, img_width),
                                                             batch_size=BATCH_SIZE
                                                            )

1.3 查看训练数据的前9张图片.

plt.figure(figsize=(6, 6))
for imgs, labels in train_ds.take(1):
    for i in range(9):
        ax = plt.subplot(3,3,i+1)
        plt.imshow(imgs[i].numpy().astype("uint8"))
        plt.title(class_names[labels[i]])
        plt.axis("off")

在这里插入图片描述

(二) 通过 tf 的基础类,自定义模型

class Mymodel(tf.keras.Model):
    def __init__(self):
        super().__init__()
        # 定义normalization 层
        self.normalization_layer = tf.keras.layers.experimental.preprocessing.Rescaling(1.0 / 255)
        
        # 定义数据增强层
        self.aug1 = tf.keras.layers.experimental.preprocessing.RandomFlip('horizontal')
        self.aug2 = tf.keras.layers.experimental.preprocessing.RandomRotation(0.1)
        self.aug3 = tf.keras.layers.experimental.preprocessing.RandomZoom(0.1)
        
        # 定义cov1
        self.cov1 = tf.keras.layers.Conv2D(16, (3,3), padding='same', activation='relu', name='cov1')
        self.pool1 = tf.keras.layers.MaxPool2D(name='pool1')
        
        # 定义cov2
        self.cov2 = tf.keras.layers.Conv2D(32, (3,3), padding='same', activation='relu', name='cov2')
        self.pool2 = tf.keras.layers.MaxPool2D(name='pool2')
        
        # 定义cov3
        self.cov3 = tf.keras.layers.Conv2D(64, (3,3), padding='same', activation='relu', name='cov3')
        self.pool3 = tf.keras.layers.MaxPool2D(name='pool3')
        
        # 定义 Dropout
        self.dropout = tf.keras.layers.Dropout(0.2)
        
        # 定义 flatten
        self.flatten = tf.keras.layers.Flatten()
        
        # 定义 Dense
        self.dense1 = tf.keras.layers.Dense(128, activation='relu', name='dense1')
        self.dense2 = tf.keras.layers.Dense(5)
        
        
    def call(self, img):
        # 执行normalization
        X = self.normalization_layer(img)
        
        # 执行aug
        X = self.aug1(X)
        X = self.aug2(X)
        X = self.aug3(X)
        
        X = self.cov1(X)
        X = self.pool1(X)
        
        X = self.cov2(X)
        X = self.pool2(X)
        
        X = self.cov3(X)
        X = self.pool3(X)
        
        X = self.flatten(X)
        X =  self.dense1(X)
        X = self.dense2(X)
        
        return X

(三) 定义损失函数

def loss(y_true, y_predict):
    return tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)(y_true, y_predict)

(四) 定义优化函数

optimizer = tf.keras.optimizers.Adam()

(五) 定义训练函数

def train_step(batch_inp, batch_targ, model):
    with tf.GradientTape() as tape:
        dense_ = model(batch_inp)
    
        batch_loss = loss(batch_targ, dense_)
    gradients = tape.gradient(batch_loss, model.trainable_variables)
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))
    return batch_loss

(六) 训练模型

# 实例化模型
model = Mymodel()

epochs = 50  # 训练50个epoch
els = [] # 存储每个epoch的损失函数,用于后续绘图
for epoch in range(epochs):
    epoch_loss = 0
	# 由于我的计算机显存太小,这里每个epoch只取前20个batch进行训练
    for batch, (inp, targ) in enumerate(train_ds.take(20)):
        batch_loss = train_step(inp, targ, model)
        epoch_loss += batch_loss.numpy()
    print('epoch {}: {:.4f}'.format(epoch, epoch_loss/10))
    els.append(epoch_loss/10)

训练过程如下:

epoch 0: 0.5867
epoch 1: 0.6709
epoch 2: 0.6393
epoch 3: 0.6831
epoch 4: 0.6870
epoch 5: 0.6461
epoch 6: 0.4888

Loss 随训练过程的变化情况:

在这里插入图片描述

(七) 通过模型进行预测

预测的代码来之 TensorFlow 官方社区。

sunflower_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/592px-Red_sunflower.jpg"
sunflower_path = tf.keras.utils.get_file('Red_sunflower', origin=sunflower_url)

img = keras.preprocessing.image.load_img(
    sunflower_path, target_size=(img_height, img_width)
)
img_array = keras.preprocessing.image.img_to_array(img)
img_array = tf.expand_dims(img_array, 0) # Create a batch

predictions = model.predict(img_array)
score = tf.nn.softmax(predictions[0])

print(
    "This image most likely belongs to {} with a {:.2f} percent confidence."
    .format(class_names[np.argmax(score)], 100 * np.max(score))
)

图片为:

在这里插入图片描述

预测结果:

This image most likely belongs to sunflowers with a 97.69 percent confidence.

  • 2
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值