Tensorflow模型训练过程数据集的使用

Tensorflow模型训练过程需要使用训练集和测试集,这里涉及比较细节的方式,其中ndarry类型和Dataset类型是最常用的两种类型,很多开发者没有完成理解清楚这两种在引用和使用过程需要注意的细节,造成运行过程出现错误,本文对这一问题通过实例进行解释和说明。

一、tensorflow模型训练可以使用的数据类型

tensorflow在训练模型的过程中,如果需要训练的数据量不是很大,例如不到1G,那么可以直接全部读入内存中进行训练,这样一般效率最高。但如果需要训练的数据很大,例如超过10G,无法一次载入内存,那么通常需要在训练的过程中分批逐渐读入。使用tf.data API可以构建数据输入管道,处理大量的数据,不同的数据格式以及不同的数据转换。
tensorflow可以直接载入的数据类型主要包括以下几种:

  1. 从Numpy array构建数据管道
  2. 从Pandas DataFrame构建数据管道
  3. 从Python generator构建数据管道
  4. 从csv文件构建数据管道
  5. 从文本文件构建数据管道
  6. 从文件路径构建数据管道
  7. 从tfrecords文件构建数据管道
    在这里介绍训练集采用ndarray和tensorflow中dataset格式作为训练集数据涉及的问题

二、tensorflow模型训练中使用ndarry类型和Dataset类型的说明

ndarry类型和Dataset类型是tensorflow中最常用两种类型,它们两个各自有各自的优势,总结起来,ndarry类型数据直接看见,开发者可以清楚的知道任意一个位置的数据,可以与其它数学算法的接口良好匹配,但在tensorflow中使用的时候需要进行一些手动操作,这对初级者来说容易出现错误;Dataset类型是则进行了比较好的封装,是tensorflow自带的数据类型,可以在tensorflow中形成非常好的兼容关系,自带了多种方法,使用起来比较简单,但数据对用户来说不是直接可见,很多算法功能包的接口不支持Dataset类型,需要开发者自己进行转换。

2.1 使用ndarry类型的实例说明:

代码:

import numpy as np
import tensorflow as tf
from tensorflow.keras.utils import plot_model
import random

mnist = tf.keras.datasets.mnist
data0 = tf.keras.datasets.mnist.load_data()
print('data0 type:',type(data0))
print('data0 len:',len(data0))
data0_0 = tf.keras.datasets.mnist.load_data()[0]
print('data0_0 type:',type(data0_0))
print('data0_0 len:',len(data0_0))
data0_0_0 = tf.keras.datasets.mnist.load_data()[0][0]
data0_0_1 = tf.keras.datasets.mnist.load_data()[0][1]
print('data0_0_0 type:',type(data0_0_0))
print('data0_0_0 shape:',np.shape(tf.keras.datasets.mnist.load_data()[0][0]))
print('data0_0_1 shape:',np.shape(tf.keras.datasets.mnist.load_data()[0][1]))

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

print("训练集样本及标签", train_images.shape, train_labels.shape)
print("测试集样本及标签", test_images.shape, test_labels.shape)
train_images, test_images = train_images / 255.0, test_images / 255.0  

index1 = [i for i in range(60000)]
random.shuffle(index1)
train_images = train_images[index1,:,:,:]
train_labels = train_labels[index1]

train_images = np.expand_dims(train_images,axis=-1)
test_images = np.expand_dims(test_images,axis=-1)
print(train_images.shape)

# 建立各层神经网络
model = tf.keras.models.Sequential()  # 建立一个堆叠层的神经网络
model.add(tf.keras.layers.Conv2D(32, (5, 5), activation='relu', padding='same', input_shape=(28, 28, 1)))

model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Conv2D(64, (5, 5), activation='relu', padding='same'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(10))  # 最后输出10个数

# 编译模型
model.compile(optimizer='adam',  # Adam优化器
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),  # 损失函数
              metrics=['accuracy'])  # 监控指标:精度
# 开始训练,训练周期8,即将所有训练样本(6万个),遍历八遍,因为输入通道是32个,所以每遍训练1875次,每次32个

plot_model(model, to_file='model_approach1.png', show_shapes=True)
model.fit(train_images, train_labels, epochs=8, batch_size=100, validation_data=(test_images, test_labels))

# 训练完毕,使用测试集来评估模型精度
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)

print('\n最终测试集上的精度为:', test_acc)

model.save("../model/cnn_model ") 

数据集的引用:

通过以下代码keras中自带的mnist数据集的结构就明确了

data0 = tf.keras.datasets.mnist.load_data()
print('data0 type:',type(data0))
print('data0 len:',len(data0))
data0_0 = tf.keras.datasets.mnist.load_data()[0]
print('data0_0 type:',type(data0_0))
print('data0_0 len:',len(data0_0))
data0_0_0 = tf.keras.datasets.mnist.load_data()[0][0]
data0_0_1 = tf.keras.datasets.mnist.load_data()[0][1]
print('data0_0_0 type:',type(data0_0_0))
print('data0_0_0 shape:',np.shape(tf.keras.datasets.mnist.load_data()[0][0]))
print('data0_0_1 shape:',np.shape(tf.keras.datasets.mnist.load_data()[0][1]))

(1) 首先通过load_data()的方法获得整体的数据集,数据集的整体data0是tuple类型
(2) 整体的数据集的tuple变量data0含有2个元素(实际上是对应训练集和测试集)
(3) 整体的数据集的tuple变量data0的第1个元素data0_0(对应训练集)的类型也是tuple,在这里需要说明的是测试集也是以tuple类型存在的
(4) 整体的数据集的tuple变量data0的第1个元素(对应训练集)的tuple变量data0_0包含2个元素,实际上对应训练集的样本数据和训练集的样本标签
(5) 整体的数据集的tuple变量data0的第1个元素(对应训练集)的tuple变量data0_0的第1个元素是ndarray类型,这说明在这里训练集的样本数据是以ndarray类型存在的,在这里需要说明的是训练集的标签、测试集的样本数据、测试集的样本标签也是以ndarray类型存在的
(6) 整体的数据集的tuple变量data0的第1个元素(对应训练集)的tuple变量data0_0的第1个元素的ndarray变量data0_0_0(对应训练集的样本)的shape是(60000,28,28),这说明每个训练集样本是28×28的二维矩阵,一共有60000个样本
(7) 整体的数据集的tuple变量data0的第1个元素(对应训练集)的tuple变量data0_0的第2个元素的ndarray变量data0_0_1(对应训练集的样本)的shape是(60000,),这说明每个训练集的标签一共有60000个,一个样本对应一个标签。
在这里插入图片描述

数据集的使用:

在这里插入图片描述
建立模型后,在训练和验证的过程中需要使用数据集(样本数据,标签),在训练过程中可以多种数据类型,可以是numpy数组、数组列表、tensorflow tensor、tensor列表;也可以是 tf.data dataset,需返回(inputs, targets) 或 (inputs, targets, sample_weights);也可以是generator or keras.utils.Sequence返回(inputs, targets) 或 (inputs, targets, sample_weights)。
在本实例中,由于使用的CNN的模型,这种模型在tensoflow中要求必须在原数据结构对应的基础上增加1维,所以这里使用了以下代码:

train_images = np.expand_dims(train_images,axis=-1)
test_images = np.expand_dims(test_images,axis=-1)

这是在ndarray的最后增加了一个维度。
由于使用的ndarray类型的数据进行训练,而ndarray中不自带shuffle和batch功能,因此需要开发者自己通过代码实现这两个功能。
在本实例中通过以下代码实现shuffle:

index1 = [i for i in range(60000)]
random.shuffle(index1)
train_images = train_images[index1,:,:,:]
train_labels = train_labels[index1]

在本实例中通过以下在model.fit中指定batchsize实现指定batch的功能:

model.fit(train_images, train_labels, epochs=8, batch_size=100, validation_data=(test_images, test_labels))

可以看出,使用ndarray类型需要开发者手动完成几项操作,但是可以清楚的搞明白数据集的结构。

2.2 使用Dataset类型的实例说明

代码:

###########  dataset approach 1: Dataset  ########################
import tensorflow as tf
from tensorflow.keras.utils import plot_model

# 加载MNIST数据集
mnist = tf.keras.datasets.mnist.load_data()

# 将数据集转换为tf.data.Dataset格式
train_dataset = tf.data.Dataset.from_tensor_slices(mnist[0])
test_dataset = tf.data.Dataset.from_tensor_slices(mnist[1])
print(type(train_dataset))

# 对训练数据集进行处理
train_dataset = train_dataset.shuffle(buffer_size=10000)
train_dataset = train_dataset.batch(batch_size=32)
#train_dataset = train_dataset.repeat(count=5)

# 对测试数据集进行处理
test_dataset = test_dataset.batch(batch_size=32)

# 建立各层神经网络
model = tf.keras.models.Sequential()  # 建立一个堆叠层的神经网络
model.add(tf.keras.layers.Conv2D(32, (5, 5), activation='relu', padding='same', input_shape=(28, 28, 1)))

model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Conv2D(64, (5, 5), activation='relu', padding='same'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(10))  # 最后输出10个数

# 编译模型
model.compile(optimizer='adam',  # Adam优化器
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),  # 损失函数
              metrics=['accuracy'])  # 监控指标:精度

model.fit(train_dataset, epochs=5)

model.evaluate(test_dataset)

数据集的引用:

在本实例中是通过tf.data.Dataset.from_tensor_slices()将tuple类型的数据转换为tensforlow中的Dataset类型

train_dataset = tf.data.Dataset.from_tensor_slices(mnist[0])
test_dataset = tf.data.Dataset.from_tensor_slices(mnist[1])

数据集的使用:

这里的数据集类型Dataset,ndarry类型在cnn模型下,需要将数据集额外再增加一维,而Dataset类型直接在model.fit()中使用就可以。

model.fit(train_dataset, epochs=5)

Dataset类型自带shuffle和batch功能,因此可以直接使用对象中的方法就可以了

train_dataset = train_dataset.shuffle(buffer_size=10000)
train_dataset = train_dataset.batch(batch_size=32)

从这里可以看出构造Dataset类型的数据集,使用的过程是比较简单的,但是看不到数据集的具体结构,想要引用具体的数据也是比较困难的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值