40、深入探索:TensorFlow的机制与卷积神经网络

深入探索:TensorFlow的机制与卷积神经网络

一、TensorFlow Estimators的使用

在使用TensorFlow进行机器学习任务时,Estimators是一个非常实用的工具。下面我们将介绍如何使用Estimators进行MNIST手写数字分类,以及如何将Keras模型转换为Estimator。

1. 使用Estimators进行MNIST手写数字分类
  • 步骤一:导入模块并设置超参数
import tensorflow_datasets as tfds
import tensorflow as tf
import numpy as np
BUFFER_SIZE = 10000
BATCH_SIZE = 64
NUM_EPOCHS = 20
steps_per_epoch = np.ceil(60000 / BATCH_SIZE)

这里, BUFFER_SIZE 用于打乱数据集, BATCH_SIZE 是小批量的大小, NUM_EPOCHS 是训练的轮数, steps_per_epoch 确定了每一轮的迭代次数。

  • 步骤二:定义预处理函数
def preprocess(item):
    image = item['image']
    label = item['label']
    image = tf.image.convert_image_dtype(image, tf.float32)
    image = tf.reshape(image, (-1,))
    return {'image-pixels':image}, label[..., tf.newaxis]

该函数将输入图像的类型从 uint8 转换为 tf.float32 ,并将其展平。

  • 步骤三:定义输入函数
def train_input_fn():
    datasets = tfds.load(name='mnist')
    mnist_train = datasets['train']
    dataset = mnist_train.map(preprocess)
    dataset = dataset.shuffle(BUFFER_SIZE)
    dataset = dataset.batch(BATCH_SIZE)
    return dataset.repeat()

def eval_input_fn():
    datasets = tfds.load(name='mnist')
    mnist_test = datasets['test']
    dataset = mnist_test.map(preprocess).batch(BATCH_SIZE)
    return dataset

train_input_fn 用于训练, eval_input_fn 用于评估。

  • 步骤四:定义特征列
image_feature_column = tf.feature_column.numeric_column(
    key='image-pixels', shape=(28*28))

这里定义了大小为784(28×28)的特征列,这是MNIST图像展平后的大小。

  • 步骤五:创建Estimator
dnn_classifier = tf.estimator.DNNClassifier(
    feature_columns=[image_feature_column],
    hidden_units=[32, 16],
    n_classes=10,
    model_dir='models/mnist-dnn/')

我们指定了两个隐藏层,第一个隐藏层有32个单元,第二个有16个单元,并且指定了类别数为10。

  • 步骤六:训练和评估
dnn_classifier.train(
    input_fn=train_input_fn,
    steps=NUM_EPOCHS * steps_per_epoch)
eval_result = dnn_classifier.evaluate(
    input_fn=eval_input_fn)
print(eval_result)

运行结果如下:

{'accuracy': 0.8957, 'average_loss': 0.3876346, 'loss': 0.38815108, 'global_step': 18760}
2. 将Keras模型转换为Estimator
  • 步骤一:生成数据并划分数据集
tf.random.set_seed(1)
np.random.seed(1)
x = np.random.uniform(low=-1, high=1, size=(200, 2))
y = np.ones(len(x))
y[x[:, 0] * x[:, 1]<0] = 0
x_train = x[:100, :]
y_train = y[:100]
x_valid = x[100:, :]
y_valid = y[100:]
  • 步骤二:构建Keras模型
model = tf.keras.Sequential([
    tf.keras.layers.Input(shape=(2,), name='input-features'),
    tf.keras.layers.Dense(units=4, activation='relu'),
    tf.keras.layers.Dense(units=4, activation='relu'),
    tf.keras.layers.Dense(units=4, activation='relu'),
    tf.keras.layers.Dense(1, activation='sigmoid')
])
  • 步骤三:定义输入函数
def train_input_fn(x_train, y_train, batch_size=8):
    dataset = tf.data.Dataset.from_tensor_slices(
        ({'input-features':x_train}, y_train.reshape(-1, 1)))
    return dataset.shuffle(100).repeat().batch(batch_size)

def eval_input_fn(x_test, y_test=None, batch_size=8):
    if y_test is None:
        dataset = tf.data.Dataset.from_tensor_slices(
            {'input-features':x_test})
    else:
        dataset = tf.data.Dataset.from_tensor_slices(
            ({'input-features':x_test}, y_test.reshape(-1, 1)))
    return dataset.batch(batch_size)
  • 步骤四:定义特征列
features = [
    tf.feature_column.numeric_column(
        key='input-features:', shape=(2,))
]
  • 步骤五:编译模型并转换为Estimator
model.compile(optimizer=tf.keras.optimizers.SGD(),
              loss=tf.keras.losses.BinaryCrossentropy(),
              metrics=[tf.keras.metrics.BinaryAccuracy()])
my_estimator = tf.keras.estimator.model_to_estimator(
    keras_model=model,
    model_dir='models/estimator-for-XOR/')
  • 步骤六:训练和评估
num_epochs = 200
batch_size = 2
steps_per_epoch = np.ceil(len(x_train) / batch_size)
my_estimator.train(
    input_fn=lambda: train_input_fn(x_train, y_train, batch_size),
    steps=num_epochs * steps_per_epoch)
my_estimator.evaluate(
    input_fn=lambda: eval_input_fn(x_valid, y_valid, batch_size))

运行结果如下:

{'binary_accuracy': 0.96, 'loss': 0.081909806, 'global_step': 10000}
二、卷积神经网络(CNNs)简介

CNNs是一类受人类视觉皮层启发的模型,在图像分类任务中表现出色。下面我们将介绍CNN的基本概念和卷积操作。

1. CNN的基本概念
  • 特征提取 :CNN的早期层从原始数据中提取低级特征,如边缘和斑点,后期层(通常是全连接层)使用这些特征进行预测。
  • 特征层次结构 :CNN通过逐层组合低级特征形成高级特征,例如在处理图像时,低级特征可以组合成更复杂的形状。
  • 稀疏连接和参数共享 :CNN的特征图中的单个元素只连接到输入图像的一小部分像素,并且不同的图像块使用相同的权重,这减少了网络中的参数数量,提高了捕捉显著特征的能力。

CNN通常由多个卷积层和下采样层(池化层)组成,最后是一个或多个全连接层。池化层没有可学习的参数,而卷积层和全连接层有需要在训练过程中优化的权重和偏置。

2. 离散卷积操作

离散卷积是CNN中的基本操作,下面我们将介绍一维离散卷积的数学定义和计算方法。

  • 数学定义 :对于两个向量 $x$ 和 $w$,离散卷积 $y = x * w$ 定义为:
    $y[i] = \sum_{k=-\infty}^{+\infty} x[i - k] w[k]$
    在实际应用中,由于我们处理的是有限特征向量,需要对 $x$ 进行零填充,以解决索引范围为 $-\infty$ 到 $+\infty$ 的问题。假设原始输入 $x$ 有 $n$ 个元素,滤波器 $w$ 有 $m$ 个元素($m \leq n$),填充后的向量 $x_p$ 的大小为 $n + 2p$,则实际的计算公式为:
    $y[i] = \sum_{k=0}^{m - 1} x_p[i + m - k] w[k]$

  • 计算方法 :计算离散卷积时,需要注意 $x$ 和 $w$ 的索引方向不同。可以通过翻转其中一个向量,然后计算它们的点积来实现。例如,翻转滤波器 $w$ 得到 $w_r$,计算 $x[i: i + m]$ 和 $w_r$ 的点积得到 $y[i]$,然后使用滑动窗口方法计算所有输出元素。

下面是一个计算一维离散卷积的示例:
输入向量 $x = [3, 2, 1, 7, 1, 2, 5, 4]$,滤波器 $w = [1, 2, 3, 4, 1, 1, 4]$,通过上述方法可以计算出输出向量的前三个元素。

通过以上内容,我们了解了如何使用TensorFlow的Estimators进行分类任务,以及如何将Keras模型转换为Estimator。同时,我们还介绍了卷积神经网络的基本概念和离散卷积操作,这些知识为我们进一步深入学习和应用CNN奠定了基础。

三、二维离散卷积操作

在实际的图像数据处理中,二维离散卷积更为常见。接下来我们详细介绍二维离散卷积的数学定义和计算方法。

1. 数学定义

对于二维矩阵 (X_{n_1\times n_2}) 和二维滤波器 (W_{m_1\times m_2})(其中 (m_1\leq n_1) 且 (m_2\leq n_2)),二维离散卷积 (Y = X * W) 的元素 (Y[i,j]) 定义为:
[Y[i,j]=\sum_{k_1 =-\infty}^{+\infty}\sum_{k_2=-\infty}^{+\infty}X[i - k_1,j - k_2]W[k_1,k_2]]
同样,在实际应用中,为了解决无限索引的问题,需要对矩阵 (X) 进行零填充。假设在两个维度上分别填充 (p_1) 和 (p_2) 个零,填充后的矩阵 (X_p) 的大小为 ((n_1 + 2p_1)\times(n_2+ 2p_2)),则实际计算公式为:
[Y[i,j]=\sum_{k_1 = 0}^{m_1 - 1}\sum_{k_2=0}^{m_2 - 1}X_p[i + m_1 - k_1,j + m_2 - k_2]W[k_1,k_2]]

2. 计算方法

与一维离散卷积类似,计算二维离散卷积时,需要注意 (X) 和 (W) 的索引方向。可以通过翻转滤波器 (W)(在两个维度上都进行翻转)得到 (W_r),然后将 (W_r) 与 (X) 的对应子矩阵进行点积运算。具体步骤如下:
1. 对输入矩阵 (X) 进行零填充。
2. 翻转滤波器 (W) 得到 (W_r)。
3. 将 (W_r) 依次滑过 (X) 的每个位置,计算对应子矩阵与 (W_r) 的点积,得到输出矩阵 (Y) 的元素。

以下为计算二维离散卷积的示例:
假设输入矩阵 (X=\begin{bmatrix}
1 & 2 & 3\
4 & 5 & 6\
7 & 8 & 9
\end{bmatrix}),滤波器 (W=\begin{bmatrix}
1 & 0\
0 & 1
\end{bmatrix}),通过上述方法可以计算出输出矩阵 (Y)。

四、在TensorFlow中实现深度CNN

在了解了CNN的基本概念和卷积操作后,我们可以在TensorFlow中实现深度CNN。下面以MNIST手写数字分类为例,介绍具体的实现步骤。

1. 数据加载与预处理
import tensorflow as tf
import tensorflow_datasets as tfds

# 加载MNIST数据集
(ds_train, ds_test), ds_info = tfds.load(
    'mnist',
    split=['train', 'test'],
    shuffle_files=True,
    as_supervised=True,
    with_info=True
)

# 数据预处理函数
def normalize_img(image, label):
    return tf.cast(image, tf.float32) / 255., label

# 应用预处理函数
ds_train = ds_train.map(
    normalize_img, num_parallel_calls=tf.data.AUTOTUNE)
ds_train = ds_train.cache()
ds_train = ds_train.shuffle(ds_info.splits['train'].num_examples)
ds_train = ds_train.batch(128)
ds_train = ds_train.prefetch(tf.data.AUTOTUNE)

ds_test = ds_test.map(
    normalize_img, num_parallel_calls=tf.data.AUTOTUNE)
ds_test = ds_test.batch(128)
ds_test = ds_test.cache()
ds_test = ds_test.prefetch(tf.data.AUTOTUNE)
2. 构建CNN模型
model = tf.keras.models.Sequential([
    tf.keras.layers.Conv2D(32, kernel_size=(3, 3),
                           activation='relu',
                           input_shape=(28, 28, 1)),
    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
    tf.keras.layers.Conv2D(64, kernel_size=(3, 3), activation='relu'),
    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10, activation='softmax')
])

在这个模型中,我们使用了两个卷积层和两个最大池化层,最后是一个全连接层和一个输出层。

3. 编译和训练模型
model.compile(
    optimizer=tf.keras.optimizers.Adam(0.001),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
    metrics=[tf.keras.metrics.SparseCategoricalAccuracy()],
)

model.fit(
    ds_train,
    epochs=6,
    validation_data=ds_test,
)
4. 评估模型
test_loss, test_acc = model.evaluate(ds_test)
print(f'Test accuracy: {test_acc}')
五、数据增强技术

数据增强是提高模型泛化性能的有效方法,通过对训练数据进行随机变换,可以增加数据的多样性,从而使模型能够学习到更鲁棒的特征。以下是一些常见的数据增强技术及其在TensorFlow中的实现。

1. 随机翻转
data_augmentation = tf.keras.Sequential([
    tf.keras.layers.RandomFlip('horizontal'),
])
2. 随机旋转
data_augmentation.add(tf.keras.layers.RandomRotation(0.1))
3. 随机缩放
data_augmentation.add(tf.keras.layers.RandomZoom(0.1))

可以将数据增强层添加到模型的开头,例如:

model = tf.keras.models.Sequential([
    data_augmentation,
    tf.keras.layers.Conv2D(32, kernel_size=(3, 3),
                           activation='relu',
                           input_shape=(28, 28, 1)),
    # 其他层...
])
六、实现基于人脸图像的CNN分类器

我们可以使用上述知识实现一个基于人脸图像的CNN分类器,用于预测人的性别。以下是大致的实现步骤:

  1. 数据收集 :收集包含人脸图像和对应性别标签的数据集。
  2. 数据预处理 :对图像进行归一化、裁剪等操作。
  3. 构建CNN模型 :参考前面的示例,构建一个适合人脸图像分类的CNN模型。
  4. 数据增强 :应用数据增强技术提高模型的泛化性能。
  5. 训练模型 :使用训练数据对模型进行训练。
  6. 评估模型 :使用测试数据评估模型的性能。

通过以上步骤,我们可以实现一个简单的基于人脸图像的CNN分类器。在实际应用中,还可以根据具体需求对模型进行优化和调整。

综上所述,我们深入探讨了TensorFlow的Estimators的使用、卷积神经网络的基本概念和操作、在TensorFlow中实现深度CNN、数据增强技术以及基于人脸图像的CNN分类器的实现。这些知识为我们在图像分类等领域的应用提供了坚实的基础。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值