深入探索:TensorFlow 机制与卷积神经网络
1. TensorFlow 特征列与预建估计器的使用
当类别数量较多时,使用维度少于类别数的嵌入列可以提升性能。以下代码展示了如何使用指示列方法将分类特征转换为密集格式:
categorical_indicator_features = []
categorical_indicator_features.append(
tf.feature_column.indicator_column(feature_origin))
除了上述常见的创建特征列的方法,还有哈希列和交叉列等,更多信息可参考 TensorFlow 官方文档 。
使用预建估计器进行机器学习可总结为四个步骤:
1. 定义用于数据加载的输入函数
2. 将数据集转换为特征列
3. 实例化一个估计器(可以使用预建估计器,也可以通过将 Keras 模型转换为估计器来创建新的估计器)
4. 使用估计器的 train() 、 evaluate() 和 predict() 方法
以汽车每加仑英里数(MPG)预测为例,具体操作如下:
- 步骤 1:定义训练数据的输入函数
def train_input_fn(df_train, batch_size=8):
df = df_train.copy()
train_x, train_y = df, df.pop('MPG')
dataset = tf.data.Dataset.from_tensor_slices(
(dict(train_x), train_y))
# shuffle, repeat, and batch the examples.
return dataset.shuffle(1000).repeat().batch(batch_size)
加载一批数据查看:
ds = train_input_fn(df_train_norm)
batch = next(iter(ds))
print('Keys:', batch[0].keys())
print('Batch Model Years:', batch[0]['ModelYear'])
- 步骤 2:定义测试数据的输入函数
def eval_input_fn(df_test, batch_size=8):
df = df_test.copy()
test_x, test_y = df, df.pop('MPG')
dataset = tf.data.Dataset.from_tensor_slices(
(dict(test_x), test_y))
return dataset.batch(batch_size)
- 步骤 3:定义特征列
all_feature_columns = (
numeric_features +
bucketized_features +
categorical_indicator_features)
- 步骤 4:实例化估计器并进行训练、评估和预测
regressor = tf.estimator.DNNRegressor(
feature_columns=all_feature_columns,
hidden_units=[32, 10],
model_dir='models/autompg-dnnregressor/')
EPOCHS = 1000
BATCH_SIZE = 8
total_steps = EPOCHS * int(np.ceil(len(df_train) / BATCH_SIZE))
print('Training Steps:', total_steps)
regressor.train(
input_fn=lambda:train_input_fn(
df_train_norm, batch_size=BATCH_SIZE),
steps=total_steps)
reloaded_regressor = tf.estimator.DNNRegressor(
feature_columns=all_feature_columns,
hidden_units=[32, 10],
warm_start_from='models/autompg-dnnregressor/',
model_dir='models/autompg-dnnregressor/')
eval_results = reloaded_regressor.evaluate(
input_fn=lambda:eval_input_fn(df_test_norm, batch_size=8))
print('Average-Loss {:.4f}'.format(
eval_results['average_loss']))
pred_res = regressor.predict(
input_fn=lambda: eval_input_fn(
df_test_norm, batch_size=8))
print(next(iter(pred_res)))
此外,还可以尝试另一个预建估计器——提升树回归器 tf.estimator.BoostedTreeRegressor :
boosted_tree = tf.estimator.BoostedTreesRegressor(
feature_columns=all_feature_columns,
n_batches_per_layer=20,
n_trees=200)
boosted_tree.train(
input_fn=lambda:train_input_fn(
df_train_norm, batch_size=BATCH_SIZE))
eval_results = boosted_tree.evaluate(
input_fn=lambda:eval_input_fn(
df_test_norm, batch_size=8))
print('Average-Loss {:.4f}'.format(
eval_results['average_loss']))
从结果来看,提升树回归器的平均损失低于 DNN 回归器,对于小数据集来说这是预期的结果。
2. 使用估计器进行 MNIST 手写数字分类
对于这个分类问题,将使用 TensorFlow 提供的 DNNClassifier 估计器。操作步骤如下:
- 步骤 1:导入必要的库和设置超参数
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)
- 步骤 2:定义预处理函数
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]
- 步骤 3:定义输入函数
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
- 步骤 4:定义特征列
image_feature_column = tf.feature_column.numeric_column(
key='image-pixels', shape=(28*28))
- 步骤 5:实例化估计器并进行训练和评估
dnn_classifier = tf.estimator.DNNClassifier(
feature_columns=[image_feature_column],
hidden_units=[32, 16],
n_classes=10,
model_dir='models/mnist-dnn/')
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)
3. 从现有 Keras 模型创建自定义估计器
将 Keras 模型转换为估计器在学术和工业领域都很有用。以异或(XOR)问题为例,具体步骤如下:
- 步骤 1:生成数据并划分训练集和验证集
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:]
- 步骤 2:构建 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')
])
- 步骤 3:定义输入函数
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)))
# shuffle, repeat, and batch the examples.
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)))
# shuffle, repeat, and batch the examples.
return dataset.batch(batch_size)
- 步骤 4:定义特征列
features = [
tf.feature_column.numeric_column(
key='input-features:', shape=(2,))
]
- 步骤 5:编译模型并转换为估计器
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/')
- 步骤 6:使用估计器进行训练和评估
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))
4. 卷积神经网络(CNNs)基础
CNNs 最初受到人类大脑视觉皮层识别物体方式的启发。20 世纪 90 年代,Yann LeCun 及其同事提出了用于手写数字图像分类的新型神经网络架构。2019 年,Yann LeCun 因在人工智能领域的贡献获得图灵奖。
4.1 理解 CNNs 和特征层次结构
成功提取显著特征是任何机器学习算法性能的关键。传统机器学习模型依赖于领域专家提供的输入特征或基于计算的特征提取技术。而 CNNs 能够自动从原始数据中学习对特定任务最有用的特征,因此通常将 CNN 层视为特征提取器。早期层从原始数据中提取低级特征,后期层(通常是全连接层)使用这些特征来预测连续目标值或类别标签。
某些类型的多层神经网络,特别是深度卷积神经网络,通过逐层组合低级特征形成高级特征,构建所谓的特征层次结构。例如,处理图像时,早期层提取边缘和斑点等低级特征,这些特征组合形成高级特征,进而构成更复杂的形状,如建筑物、猫或狗的大致轮廓。
CNNs 在图像相关任务中表现出色,主要得益于两个重要概念:
- 稀疏连接 :特征图中的单个元素仅连接到输入图像的一小部分像素,这与感知机连接整个输入图像不同。
- 参数共享 :输入图像的不同部分使用相同的权重。
下面是使用预建估计器的步骤流程图:
graph TD;
A[定义输入函数] --> B[转换数据集为特征列];
B --> C[实例化估计器];
C --> D[使用训练、评估和预测方法];
通过以上内容,我们深入了解了 TensorFlow 的特征列、预建估计器的使用,以及如何从 Keras 模型创建自定义估计器,同时对卷积神经网络的基础概念有了初步认识。后续将进一步探讨 CNNs 的实现和应用。
深入探索:TensorFlow 机制与卷积神经网络
5. 卷积操作
在 CNNs 中,卷积操作是核心组成部分,下面分别介绍一维和二维卷积操作。
5.1 一维卷积操作
一维卷积常用于处理序列数据,如时间序列。假设有一个长度为 $n$ 的输入序列 $x = [x_1, x_2, \cdots, x_n]$ 和一个长度为 $m$ 的卷积核 $w = [w_1, w_2, \cdots, w_m]$,其中 $m \leq n$。一维卷积的计算过程如下:
1. 将卷积核 $w$ 与输入序列 $x$ 的前 $m$ 个元素对齐。
2. 对应元素相乘并求和,得到卷积结果的第一个元素。
3. 将卷积核向右移动一个位置,重复步骤 2,直到卷积核无法再与输入序列对齐。
以下是一个简单的一维卷积的 Python 示例:
import numpy as np
def conv1d(x, w):
n = len(x)
m = len(w)
result = []
for i in range(n - m + 1):
result.append(np.sum(x[i:i+m] * w))
return np.array(result)
x = np.array([1, 2, 3, 4, 5])
w = np.array([1, 0, 1])
output = conv1d(x, w)
print(output)
5.2 二维卷积操作
二维卷积常用于处理图像数据。假设有一个 $H \times W$ 的输入图像 $X$ 和一个 $h \times w$ 的卷积核 $W$,其中 $h \leq H$ 且 $w \leq W$。二维卷积的计算过程如下:
1. 将卷积核 $W$ 与输入图像 $X$ 的左上角对齐。
2. 对应元素相乘并求和,得到卷积结果的第一个元素。
3. 将卷积核向右移动一个位置(如果到达边界则向下移动一行),重复步骤 2,直到卷积核无法再与输入图像对齐。
以下是一个简单的二维卷积的 Python 示例:
import numpy as np
def conv2d(X, W):
H, W_in = X.shape
h, w = W.shape
result = np.zeros((H - h + 1, W_in - w + 1))
for i in range(H - h + 1):
for j in range(W_in - w + 1):
result[i, j] = np.sum(X[i:i+h, j:j+w] * W)
return result
X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
W = np.array([[1, 0], [0, 1]])
output = conv2d(X, W)
print(output)
6. CNN 架构的构建块
CNN 架构通常由多个构建块组成,主要包括卷积层、池化层和全连接层。
6.1 卷积层
卷积层是 CNN 的核心,它通过卷积操作提取输入数据的特征。卷积层的主要参数包括卷积核的数量、大小和步长。卷积核的数量决定了输出特征图的通道数,卷积核的大小决定了感受野的大小,步长决定了卷积核在输入数据上的移动步幅。
以下是一个使用 TensorFlow 实现卷积层的示例:
import tensorflow as tf
# 输入数据
input_data = tf.random.normal([1, 28, 28, 3])
# 定义卷积层
conv_layer = tf.keras.layers.Conv2D(filters=16, kernel_size=(3, 3), strides=(1, 1), padding='same')
# 进行卷积操作
output = conv_layer(input_data)
print(output.shape)
6.2 池化层
池化层用于减少特征图的尺寸,同时保留重要的特征信息。常见的池化操作包括最大池化和平均池化。最大池化选择每个池化窗口中的最大值作为输出,平均池化选择每个池化窗口中的平均值作为输出。
以下是一个使用 TensorFlow 实现最大池化层的示例:
import tensorflow as tf
# 输入数据
input_data = tf.random.normal([1, 28, 28, 16])
# 定义最大池化层
pool_layer = tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2))
# 进行池化操作
output = pool_layer(input_data)
print(output.shape)
6.3 全连接层
全连接层通常位于 CNN 的末尾,用于将提取的特征映射到最终的输出类别。全连接层的每个神经元与前一层的所有神经元相连。
以下是一个使用 TensorFlow 实现全连接层的示例:
import tensorflow as tf
# 输入数据
input_data = tf.random.normal([1, 7 * 7 * 16])
# 定义全连接层
fc_layer = tf.keras.layers.Dense(units=10, activation='softmax')
# 进行全连接操作
output = fc_layer(input_data)
print(output.shape)
7. 在 TensorFlow 中实现深度 CNN
下面是一个使用 TensorFlow 实现简单深度 CNN 的完整示例,用于 MNIST 手写数字分类:
import tensorflow as tf
from tensorflow.keras import layers, models
# 加载 MNIST 数据集
mnist = tf.keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
# 数据预处理
train_images = train_images.reshape((60000, 28, 28, 1))
train_images = train_images / 255.0
test_images = test_images.reshape((10000, 28, 28, 1))
test_images = test_images / 255.0
# 构建 CNN 模型
model = models.Sequential([
layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(64, (3, 3), activation='relu'),
layers.MaxPooling2D((2, 2)),
layers.Flatten(),
layers.Dense(64, activation='relu'),
layers.Dense(10, activation='softmax')
])
# 编译模型
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 训练模型
model.fit(train_images, train_labels, epochs=5)
# 评估模型
test_loss, test_acc = model.evaluate(test_images, test_labels)
print(f'Test accuracy: {test_acc}')
8. 数据增强技术
数据增强是提高模型泛化性能的有效方法,通过对训练数据进行随机变换,增加数据的多样性。常见的数据增强方法包括旋转、翻转、缩放和平移等。
以下是一个使用 TensorFlow 实现数据增强的示例:
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# 定义数据增强生成器
datagen = ImageDataGenerator(
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest'
)
# 加载 MNIST 数据集
mnist = tf.keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
# 数据预处理
train_images = train_images.reshape((60000, 28, 28, 1))
train_images = train_images / 255.0
# 生成增强后的数据
augmented_data = datagen.flow(train_images, train_labels, batch_size=32)
# 构建 CNN 模型(同上)
model = models.Sequential([
layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(64, (3, 3), activation='relu'),
layers.MaxPooling2D((2, 2)),
layers.Flatten(),
layers.Dense(64, activation='relu'),
layers.Dense(10, activation='softmax')
])
# 编译模型
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 训练模型
model.fit(augmented_data, steps_per_epoch=len(train_images) // 32, epochs=5)
# 评估模型
test_loss, test_acc = model.evaluate(test_images.reshape((10000, 28, 28, 1)) / 255.0, test_labels)
print(f'Test accuracy: {test_acc}')
9. 实现基于人脸图像的 CNN 分类器
以下是一个简单的基于人脸图像的 CNN 分类器的实现步骤:
1. 数据收集 :收集包含不同性别面部图像的数据集,并将其划分为训练集和测试集。
2. 数据预处理 :对图像进行归一化、调整大小等操作。
3. 构建 CNN 模型 :使用卷积层、池化层和全连接层构建模型。
4. 编译模型 :选择合适的优化器、损失函数和评估指标。
5. 训练模型 :使用训练集对模型进行训练。
6. 评估模型 :使用测试集评估模型的性能。
以下是一个简化的代码示例:
import tensorflow as tf
from tensorflow.keras import layers, models
# 假设已经有了训练集和测试集
train_images = ...
train_labels = ...
test_images = ...
test_labels = ...
# 数据预处理
train_images = train_images / 255.0
test_images = test_images / 255.0
# 构建 CNN 模型
model = models.Sequential([
layers.Conv2D(32, (3, 3), activation='relu', input_shape=(100, 100, 3)),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(64, (3, 3), activation='relu'),
layers.MaxPooling2D((2, 2)),
layers.Flatten(),
layers.Dense(64, activation='relu'),
layers.Dense(1, activation='sigmoid')
])
# 编译模型
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
# 训练模型
model.fit(train_images, train_labels, epochs=10)
# 评估模型
test_loss, test_acc = model.evaluate(test_images, test_labels)
print(f'Test accuracy: {test_acc}')
下面是 CNN 模型构建的步骤表格:
|步骤|操作|
|----|----|
|1|定义卷积层提取特征|
|2|使用池化层减少特征图尺寸|
|3|添加全连接层进行分类|
|4|编译模型并选择优化器、损失函数和评估指标|
|5|使用训练数据进行训练|
|6|使用测试数据评估模型性能|
通过以上内容,我们全面了解了卷积神经网络的基本概念、卷积操作、架构构建块、在 TensorFlow 中的实现、数据增强技术以及基于人脸图像的 CNN 分类器的实现。这些知识和技术可以帮助我们更好地处理图像分类问题,提高模型的性能和泛化能力。
超级会员免费看
1412

被折叠的 条评论
为什么被折叠?



