Tensorflow 笔记 Ⅻ——再梳理猫狗数据集 Transfer Learning 与 TFRecord

参考

前面已经有多篇讲解了 TensorFlow 的高速文件读取管道 TFRecord 与 迁移学习,今天再炒点不同的冷菜,本文将不在过多讲解函数与用法,如下博客可供参考:
TensorFlow实现kaggle数据集图像分类Ⅰ——tfrecord数据格式掌握
TensorFlow实现kaggle数据集图像分类Ⅱ——tfrecord数据格式制作,展示,与训练一体综合
Tensorflow 笔记 Ⅹ——Transfer Learning for Kaggle Dataset

TFRecord

TFRecord格式数据文件应用

TFRecord 是 TensorFlow 中的数据集中存储格式。将数据集整理成 TFRecord 格式后,TensorFlow 就可以高效地读取和处理这些数据集,从而更高效地进行大规模的模型训练。
TFRecord 可以理解为一系列序列化的 tf.train.Example 元素所组成的列表文件,而每一个 tf.train.Example 又由若干个 tf.train.Feature 的字典组成。形式如下:

[
{	# example 1
	'feature_1':tf.train.Feature,
	...
	'feature_k':tf.train.Feature,
},
...
{	# example N
	'feature_1':tf.train.Feature,
	...
	'feature_k':tf.train.Feature,
}
]

TFRecord格式数据文件处理过程

将形式各样的数据集整理为 TFRecord 格式,可以对数据集中的每个元素进行以下步骤:
1)读取该数据元素到内存;
2)将该元素转换为 tf.train.Example 对象(每一个 tf.train.Example 由若干个 tf.train.Feature 的字典组成,因此需要先建立 Feature 的字典);
3)将该 tf.train.Example 对象序列化为字符串,并通过一个预先定义的 tf.io.TFRecordWriter 写入 TFRecord 文件。读取 TFRecord 数据可按照以下步骤:
1)通过 tf.data.TFRecordDataset 读入原始的 TFRecord 文件(此时文件中的 tf.train.Example 对象尚未被反序列化),获得一个 tf.data.Dataset 数据集对象;
2)通过 Dataset.map 方法,对该数据集对象中的每一个序列化的 tf.train.Example 字符串执行 tf.io.parse_single_example 函数,从而实现反序列化。

代码实现

前情函数

import tensorflow as tf
import numpy as np


tf.__version__
'2.0.0'

map 函数介绍

map(
    map_func, num_parallel_calls=None
)
map函数的目的是对每一个数据进行 map_func 函数变化,例如 map_func 函数的目的是加一操作,那么 map 函数将让所有值都加一
map 函数具有两个输入,一个是 map_func,这是要求输入一个数据处理的函数,另一个是 num_parallel_calls,是并行处理时需求的参数,一般用 None 或者使用 tf.data.experimental.AUTOTUNE 来让计算机自适应并行计算

a = tf.data.Dataset.range(1, 6)
for data in a:
    print(data.numpy(), end=' ')
print('\n*********')

a_map = a.map(map_func=lambda x: x + 1)
for data in a_map:
    print(data.numpy(), end=' ')
1 2 3 4 5 
*********
2 3 4 5 6 
def func(input_data):
    return 2 * input_data

a = tf.data.Dataset.range(1, 6)
for data in a:
    print(data.numpy(), end=' ')
print('\n*********')

a_map = a.map(func)
for data in a_map:
    print(data.numpy(), end=' ')
1 2 3 4 5 
*********
2 4 6 8 10 

tf.data.Dataset.from_tensor_slices

主要针对小批量数据集

X = np.array([520, 502, 521, 555])
Y = np.array([1, 2, 3, 4])

dataset = tf.data.Dataset.from_tensor_slices((X, Y))

for x, y in dataset:
    print(x.numpy(), y.numpy())

del X; del Y
520 1
502 2
521 3
555 4

Dataset 利用 iter() 显式的创建一个 Python 迭代器并使用 next() 方法获取下一个元素

X = tf.constant([520, 502, 521, 555])
Y = tf.constant([1, 2, 3, 4])

dataset = tf.data.Dataset.from_tensor_slices((X, Y))

data_it = iter(dataset)

for i in range(len(X)):
    x, y = data_it.next()
    print(x.numpy(), y.numpy())

del X; del Y
520 1
502 2
521 3
555 4

正式开始

模块导入

import tensorflow as tf
import os
import numpy as np
import matplotlib.pyplot as plt

tf.keras.__version__
'2.2.4-tf'

文件获取函数

获取文件名并对文件名打上相应的标签

def read_image_filenames(data_dir):
    filenames = []
    labels = []
    for file in os.listdir(data_dir):
        filenames.append(os.path.join(data_dir, file))
        name = file.split('.')[0]
        if name == 'cat':
            label = 0
        else:
            label = 1
        labels.append(label)
    
    filenames = tf.constant(filenames)
    labels = tf.constant(labels)
    return filenames, labels

图像解码函数

将图像变换为矩阵,并 resize 与 归一化

def decode_image_and_resize(filename, label):
    image_string = tf.io.read_file(filename)
    image_decoded = tf.image.decode_jpeg(image_string)
    
    image_resized = tf.image.resize(image_decoded, [224, 224]) / 255.0
    
    return image_resized, label

展示读取文件与可视化

train_data_dir = './data/train1/'
filenames, labels = read_image_filenames(train_data_dir)
dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
demo_dataset = dataset.take(5)

for file, label in demo_dataset:
    print('filename:', file.numpy(), (25-len(file.numpy())) * ' ', 'label:', label.numpy())

del demo_dataset
filename: b'./data/train1/cat.0.jpg'    label: 0
filename: b'./data/train1/cat.1.jpg'    label: 0
filename: b'./data/train1/cat.10.jpg'   label: 0
filename: b'./data/train1/cat.100.jpg'  label: 0
filename: b'./data/train1/cat.1000.jpg'  label: 0
dataset = dataset.map(map_func=decode_image_and_resize,
                      num_parallel_calls=tf.data.experimental.AUTOTUNE)
demo_dataset = dataset.take(5)
fig = plt.gcf()
fig.set_size_inches(20, 4)

i = 0
for file, label in demo_dataset:
    i += 1
    ax = plt.subplot(1, 5, i)
    ax.imshow(file, cmap='binary')
    title = 'label:' + str(label.numpy())
    ax.set_title(title, fontsize=15)
plt.show()

del demo_dataset

函数重构

将前面的操作封装成一个函数,命名为 prepare_dataset

def prepare_dataset(data_dir='data/train1/', buffer_size=10000, batch_size=16):
    filenames, labels = read_image_filenames(data_dir)
    dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
    dataset = dataset.map(map_func=decode_image_and_resize,
                          num_parallel_calls=tf.data.experimental.AUTOTUNE)
    dataset = dataset.shuffle(buffer_size)
    dataset = dataset.batch(batch_size)
    dataset = dataset.prefetch(tf.data.experimental.AUTOTUNE)
    
    return dataset
dataset_train = prepare_dataset()
demo_dataset = dataset_train.take(1)
fig = plt.gcf()
fig.set_size_inches(20, 20)


for file, label in demo_dataset:
    i = 0
    for i in range(len(label)):
        ax = plt.subplot(4, 4, i+1)
        ax.imshow(file[i], cmap='binary')
        title = 'label:' + str(label.numpy()[i])
        ax.set_title(title, fontsize=20)
        ax.set_xticks([])
        ax.set_yticks([])
        i += 1

plt.show()

建立模型

def vgg16_model(input_shape=(224, 224, 3)):
    vgg16 = tf.keras.applications.vgg16.VGG16(include_top=False,
                                             weights='imagenet', 
                                             input_shape=input_shape)
    for layer in vgg16.layers:
        layer.trainable=False
    
    last = vgg16.output
    
    x = tf.keras.layers.Flatten()(last)
    x = tf.keras.layers.Dense(128, activation='relu')(x)
    x = tf.keras.layers.Dropout(0.3)(x)
    x = tf.keras.layers.Dense(32, activation='relu')(x)
    x = tf.keras.layers.Dropout(0.3)(x)
    x = tf.keras.layers.Dense(2, activation='softmax')(x)
    
    model = tf.keras.models.Model(inputs=vgg16.input, outputs=x)
    model.summary()
    
    return model

摘要输入

通过摘要可以发现,我们只需要训练 300w 参数

model = vgg16_model()
Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 224, 224, 3)]     0         
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         
_________________________________________________________________
block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     
_________________________________________________________________
block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0         
_________________________________________________________________
block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    
_________________________________________________________________
block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0         
_________________________________________________________________
block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160   
_________________________________________________________________
block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0         
_________________________________________________________________
block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0         
_________________________________________________________________
flatten (Flatten)            (None, 25088)             0         
_________________________________________________________________
dense (Dense)                (None, 128)               3211392   
_________________________________________________________________
dropout (Dropout)            (None, 128)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 32)                4128      
_________________________________________________________________
dropout_1 (Dropout)          (None, 32)                0         
_________________________________________________________________
dense_2 (Dense)              (None, 2)                 66        
=================================================================
Total params: 17,930,274
Trainable params: 3,215,586
Non-trainable params: 14,714,688
_________________________________________________________________

开始训练

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
train_epochs = 5
train_history = model.fit(dataset_train, epochs=train_epochs, verbose=1)
Epoch 1/5
625/625 [==============================] - 200s 321ms/step - loss: 0.4188 - accuracy: 0.8132
Epoch 2/5
625/625 [==============================] - 188s 301ms/step - loss: 0.2386 - accuracy: 0.9023
Epoch 3/5
625/625 [==============================] - 183s 293ms/step - loss: 0.1999 - accuracy: 0.9196
Epoch 4/5
625/625 [==============================] - 182s 291ms/step - loss: 0.1626 - accuracy: 0.9371
Epoch 5/5
625/625 [==============================] - 181s 290ms/step - loss: 0.1365 - accuracy: 0.9449

模型存储

需要安装 pyyaml,在终端输入 pip install pyyaml,或在 jupyter 输入 !pip install pyyaml

if not os.path.exists('./yaml_models'):
    os.mkdir('./yaml_models')

yaml_string = model.to_yaml()

with open('./yaml_models/cat_vs_dog.yaml', 'w') as model_file:
    model_file.write(yaml_string)

model.save_weights('./yaml_models/cat_vs_dog.h5')

应用模型与可视化

with open('./yaml_models/cat_vs_dog.yaml') as yamlfile:
    loaded_model_yaml = yamlfile.read()

model = tf.keras.models.model_from_yaml(loaded_model_yaml)
model.load_weights('./yaml_models/cat_vs_dog.h5')

随机选取 num 张进行预测

from tensorflow.keras.preprocessing import image

def read_image_files(test_dir='./data/test1', num=16, image_size=(224, 224)):
    image_name_list = []
    image_list = []
    files = os.listdir(test_dir)
    for i in range(num):
        choose = np.random.randint(len(files))
        image_file = os.path.join(test_dir, files[choose])
        files.remove(files[choose])
        img = image.load_img(image_file, target_size=image_size)
        img_array = image.img_to_array(img)
        image_list.append(img_array)
        image_name_list.append(files[choose])
    test_data = np.array(image_list)
    test_data /= 255.0
    print('INFO:%d images have been loaded!' % num)
    return test_data, image_name_list, image_list, num
import math

def predict_show():
    test_data, image_name_list, image_list, num = read_image_files()
    preds = model.predict(test_data)
    result = np.argmax(preds, 1)

    fig = plt.gcf()
    fig.set_size_inches(20, 20)

    i = 0
    for probs in result:
        ax = plt.subplot(math.ceil(num / 4), 4, i+1)
        ax.imshow(image_list[i].astype('uint8'), cmap='binary')
        if probs == 0:
            label = 'cat→'+ image_name_list[i] + ' probs:' + str(preds[i][0])
        else:
            label = 'dog→' + image_name_list[i] + ' probs:' +str(preds[i][1])
        i += 1
        ax.set_title(label, fontsize=15)
        ax.set_xticks([])
        ax.set_yticks([])

    plt.show()
predict_show()
INFO:16 images have been loaded!

TFRecord 制作

定义文件与标签获取函数

def get_image_filenames(data_dir):
    filenames = []
    labels = []
    for file in os.listdir(data_dir):
        filenames.append(os.path.join(data_dir, file))
        name = file.split('.')[0]
        if name == 'cat':
            label = 0
        else:
            label = 1
        labels.append(label)

    return filenames, labels

定义 TFRecord 写入函数

def write_TFRecord_file(filenames, labels, tfrecord_file):
    with tf.io.TFRecordWriter(tfrecord_file) as writer:
        for filename, label in zip(filenames, labels):
            image = open(filename, 'rb').read()
            feature={
                'image': tf.train.Feature(bytes_list=tf.train.BytesList(value=[image])),
                'label': tf.train.Feature(int64_list=tf.train.Int64List(value=[label]))
            }
            example = tf.train.Example(features=tf.train.Features(feature=feature))
            
            writer.write(example.SerializeToString())

开始写入

tfrecord_file = 'data/train1.tfrecords'

if not os.path.isfile(tfrecord_file):
    filenames, labels = get_image_filenames('data/train1')
    write_TFRecord_file(filenames, labels, tfrecord_file)
    print('INFO: TFRecord file has been wrote to', tfrecord_file, '.')
else:
    print('INFO: TFRecord file already exists.')
INFO: TFRecord file already exists.

TFRecord 解码与可视化

定义描述字典

features_description={
   'label': tf.io.FixedLenFeature([], tf.int64),
   'image' : tf.io.FixedLenFeature([], tf.string),
}

def parse_example(example_string):
    features_dict = tf.io.parse_single_example(example_string, features_description)
    features_dict['image'] = tf.io.decode_jpeg(features_dict['image'])
    features_dict['image'] = tf.image.resize(features_dict['image'], [224, 224]) / 255.0
    
    return features_dict['image'], features_dict['label']

定义解码读取函数

def read_TFRecord_file(tfrecord_file):
    raw_dataset = tf.data.TFRecordDataset(tfrecord_file)
    dataset = raw_dataset.map(parse_example)
    
    return dataset

解码与可视化

buffer_size = 10000

batch_size = 16

dataset_train = read_TFRecord_file(tfrecord_file).shuffle(buffer_size).batch(batch_size)
dataset_train
<BatchDataset shapes: ((None, 224, 224, None), (None,)), types: (tf.float32, tf.int64)>
demo_dataset = dataset_train.take(1)
fig = plt.gcf()
fig.set_size_inches(20, 20)


for file, label in demo_dataset:
    i = 0
    for i in range(len(label)):
        ax = plt.subplot(4, 4, i+1)
        ax.imshow(file[i], cmap='binary')
        title = 'label:' + str(label.numpy()[i])
        ax.set_title(title, fontsize=20)
        ax.set_xticks([])
        ax.set_yticks([])
        i += 1

plt.show()

陷入无尽的循环吧

殊途同归,最终利用 TFRecord 得到最初 dataset,照着前面的葫芦就可以开始训练了,这里省略XX字

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FPGA自学笔记——设计与验证JMB FPGA(可编程逻辑门阵列)是一种可编程的硬件平台,可以实现各种数字电路的设计与验证。本文将简要介绍使用FPGA自学设计与验证JMB(低功耗、高效能、集成度高的多媒体芯片)的过程。 首先,我们需要了解JMB的功能和特性。JMB是一种面向多媒体应用的芯片,具备低功耗、高效能和高集成度的优势。我们需要详细研究JMB的硬件架构和内部模块,包括处理器核、存储器模块、图像和音频处理模块等。 接下来,我们可以使用FPGA开发板来设计和验证JMB。首先,我们需要熟悉FPGA设计工具,例如Vivado或Quartus等。这些工具提供了图形化界面和硬件描述语言(HDL)等设计方法。我们可以使用HDL编写JMB的功能模块,并将其综合为FPGA可执行的位流文件。 在设计完成后,我们需要验证JMB的功能和性能。我们可以使用仿真工具(例如ModelSim或ISE Simulator)来模拟JMB在不同情况下的行为。通过设计测试程序并运行仿真,我们可以验证JMB的各个模块是否正确地工作,是否满足设计要求。 在验证完成后,我们可以将位流文件下载到FPGA开发板中进行智能芯片的物理实现和测试。通过与外部设备的连接以及相关测试程序的运行,我们可以验证JMB在实际硬件中的功能和性能。 总结起来,学习FPGA设计与验证JMB,我们需要熟悉JMB的硬件架构和内部模块,并使用FPGA开发工具进行设计与验证。通过仿真和物理实现测试,我们可以验证JMB的功能和性能。这些过程需要理论知识和实践经验的结合,希望这些笔记能够给你提供一些参考和指导。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值