google机器学习速成课程总结

Google新出的16小时机器学习速成课程,主要针对TensorFlow,记一些重点。主题不支持MathJax,公式省略。


机器学习概念


机器学习主要术语

标签

在简单线性回归中,标签是我们要预测的事物,即 y 变量。标签可以是小麦未来的价格、图片中显示的动物品种、音频剪辑的含义或任何事物。

特征

在简单线性回归中,特征是输入变量,即 x 变量。简单的机器学习项目可能会使用单个特征,而比较复杂的机器学习项目可能会使用数百万个特征,按如下方式指定:

在垃圾邮件检测器示例中,特征可能包括:

  • 电子邮件文本中的字词
  • 发件人的地址
  • 发送电子邮件的时段
  • 电子邮件中包含“一种奇怪的把戏”这样的短语。

样本

样本是指数据的特定实例:x。(我们采用粗体 x 表示它是一个矢量。)我们将样本分为以下两类:

  • 有标签样本
  • 无标签样本

模型

模型定义了特征与标签之间的关系。例如,垃圾邮件检测模型可能会将某些特征与“垃圾邮件”紧密联系起来。我们来重点介绍一下模型生命周期的两个阶段:

  • 训练表示创建或学习模型。也就是说,您向模型展示有标签样本,让模型逐渐学习特征与标签之间的关系。

  • 推断表示将训练后的模型应用于无标签样本。也就是说,您使用训练后的模型来做出有用的预测 (y’)。

回归与分类

  • 回归模型可预测连续值。例如,回归模型做出的预测可回答如下问题:

  • 分类模型可预测离散值。例如,分类模型做出的预测可回答如下问题:


线性回归


训练与损失

损失是对糟糕预测的惩罚。也就是说,损失是一个数值,表示对于单个样本而言模型预测的准确程度。如果模型的预测完全准确,则损失为零,否则损失会较大。训练模型的目标是从所有样本中找到一组平均损失“较小”的权重和偏差。

  • 平方损失(又称为 L2 损失)

  • 均方误差 (MSE)

    求出各个样本的所有平方损失之和,然后除以样本数量


降低损失(Reducing Loss)

  • 迭代方法

  • 梯度下降法

  • 学习速率

  • 优化学习速率

  • 随机梯度下降法(SGD)

    小批量随机梯度下降法(小批量 SGD)是介于全批量迭代与 SGD 之间的折衷方案。小批量通常包含 10-1000 个随机选择的样本。小批量 SGD 可以减少 SGD 中的杂乱样本数量,但仍然比全批量更高效。


使用 TensorFlow 的起始步骤

工具包 说明
Estimator (tf.estimator) 高级 OOP API
tf.layers/tf.losses/tf.metrics 用于常见模型组件的库
TensorFlow 低级 API

TensorFlow 由以下两个组件组成:

  • 图协议缓冲区(Protocol Buffers)
  • 执行(分布式)图的运行时
import tensorflow as tf

# Set up a linear classifier.
classifier = tf.estimator.LinearClassifier()

# Train the model on some example data.
classifier.train(input_fn=train_input_fn, steps=2000)

# Use it to predict.
predictions = classifier.predict(input_fn=predict_input_fn)

一个例子:
在 TensorFlow 中使用 LinearRegressor 类并基于单个输入特征预测各城市街区的房屋价值中位数
使用均方根误差 (RMSE) 评估模型预测的准确率
通过调整模型的超参数提高模型准确率

import math

from IPython import display
from matplotlib import cm
from matplotlib import gridspec
from matplotlib import pyplot as plt
import numpy as np
import pandas as pd
from sklearn import metrics
import tensorflow as tf
from tensorflow.python.data import Dataset

tf.logging.set_verbosity(tf.logging.ERROR)
pd.options.display.max_rows = 10
pd.options.display.float_format = '{:.1f}'.format

california_housing_dataframe = pd.read_csv("https://storage.googleapis.com/ml_universities/california_housing_train.csv", sep=",")

# 随机化处理
california_housing_dataframe = california_housing_dataframe.reindex(
np.random.permutation(california_housing_dataframe.index))
california_housing_dataframe["median_house_value"] /= 1000.0
california_housing_dataframe

# 检查数据
california_housing_dataframe.describe()

# Define the input feature: total_rooms.
my_feature = california_housing_dataframe[["total_rooms"]]

# Configure a numeric feature column for total_rooms.
feature_columns = [tf.feature_column.numeric_column("total_rooms")]

# Define the label.
targets = california_housing_dataframe["median_house_value"]

# Use gradient descent as the optimizer for training the model.
my_optimizer=tf.train.GradientDescentOptimizer(learning_rate=0.0000001)

# 梯度裁剪 (gradient clipping)
my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)

# Configure the linear regression model with our feature columns and optimizer.
# Set a learning rate of 0.0000001 for Gradient Descent.
linear_regressor = tf.estimator.LinearRegressor(
feature_columns=feature_columns,
optimizer=my_optimizer
)

def my_input_fn(features, targets, batch_size=1, shuffle=True, num_epochs=None):
"""Trains a linear regression model of one feature.

Args:
features: pandas DataFrame of features
targets: pandas DataFrame of targets
batch_size: Size of batches to be passed to the model
shuffle: True or False. Whether to shuffle the data.
num_epochs: Number of epochs for which data should be repeated. None = repeat indefinitely
Returns:
Tuple of (features, labels) for next data batch
"""

# Convert pandas data into a dict of np arrays.
features = {key:np.array(value) for key,value in dict(features).items()}

# Construct a dataset, and configure batching/repeating
ds = Dataset.from_tensor_slices((features,targets)) # warning: 2GB limit
ds = ds.batch(batch_size).repeat(num_epochs)

# Shuffle the data, if specified
if shuffle:
ds = ds.shuffle(buffer_size=10000)

# Return the next batch of data
features, labels = ds.make_one_shot_iterator().get_next()
return features, labels

_ = linear_regressor.train(
input_fn = lambda:my_input_fn(my_feature, targets),
steps=100
)

# Create an input function for predictions.
# Note: Since we're making just one prediction for each example, we don't
# need to repeat or shuffle the data here.
prediction_input_fn =lambda: my_input_fn(my_feature, targets, num_epochs=1, shuffle=False)

# Call predict() on the linear_regressor to make predictions.
predictions = linear_regressor.predict(input_fn=prediction_input_fn)

# Format predictions as a NumPy array, so we can calculate error metrics.
predictions = np.array([item['predictions'][0] for item in predictions])

# Print Mean Squared Error and Root Mean Squared Error.
mean_squared_error = metrics.mean_squared_error(predictions, targets)
root_mean_squared_error = math.sqrt(mean_squared_error)
print "Mean Squared Error (on training data): %0.3f" % mean_squared_error
print "Root Mean Squared Error (on training data): %0.3f" % root_mean_squared_error

写成一个函数:

def train_model(learning_rate, steps, batch_size, input_feature="total_rooms"):
"""Trains a linear regression model of one feature.

Args:
learning_rate: A `float`, the learning rate.
steps: A non-zero `int`, the total number of training steps. A training step
consists of a forward and backward pass using a single batch.
batch_size: A non-zero `int`, the batch size.
input_feature: A `string` specifying a column from `california_housing_dataframe`
to use as input feature.
"""

periods = 10
steps_per_period = steps / periods

my_feature = input_feature
my_feature_data = california_housing_dataframe[[my_feature]]
my_label = "median_house_value"
targets = california_housing_dataframe[my_label]

# Create feature columns
feature_columns = [tf.feature_column.numeric_column(my_feature)]

# Create input functions
training_input_fn = lambda:my_input_fn(my_feature_data, targets, batch_size=batch_size)
prediction_input_fn = lambda: my_input_fn(my_feature_data, targets, num_epochs=1, shuffle=False)

# Create a linear regressor object.
my_optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)
my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)
linear_regressor = tf.estimator.LinearRegressor(
feature_columns=feature_columns,
optimizer=my_optimizer
)

# Set up to plot the state of our model's line each period.
plt.figure(figsize=(15, 6))
plt.subplot(1, 2, 1)
plt.title("Learned Line by Period")
plt.ylabel(my_label)
plt.xlabel(my_feature)
sample = california_housing_dataframe.sample(n=300)
plt.scatter(sample[my_feature], sample[my_label])
colors = [cm.coolwarm(x) for x in np.linspace(-1, 1, periods)]

# Train the model, but do so inside a loop so that we can periodically assess
# loss metrics.
print "Training model..."
print "RMSE (on training data):"
root_mean_squared_errors = []
for period in range (0, periods):
# Train the model, starting from the prior state.
linear_regressor.train(
input_fn=training_input_fn,
steps=steps_per_period
)
# Take a break and compute predictions.
predictions = linear_regressor.predict(input_fn=prediction_input_fn)
predictions = np.array([item['predictions'][0] for item in predictions])

# Compute loss.
root_mean_squared_error = math.sqrt(
metrics.mean_squared_error(predictions, targets))
# Occasionally print the current loss.
print " period %02d : %0.2f" % (period, root_mean_squared_error)
# Add the loss metrics from this period to our list.
root_mean_squared_errors.append(root_mean_squared_error)
# Finally, track the weights and biases over time.
# Apply some math to ensure that the data and line are plotted neatly.
y_extents = np.array([0, sample[my_label].max()])

weight = linear_regressor.get_variable_value('linear/linear_model/%s/weights' % input_feature)[0]
bias = linear_regressor.get_variable_value('linear/linear_model/bias_weights')

x_extents = (y_extents - bias) / weight
x_extents = np.maximum(np.minimum(x_extents,
sample[my_feature].max()),
sample[my_feature].min())
y_extents = weight * x_extents + bias
plt.plot(x_extents, y_extents, color=colors[period])
print "Model training finished."

# Output a graph of loss metrics over periods.
plt.subplot(1, 2, 2)
plt.ylabel('RMSE')
plt.xlabel('Periods')
plt.title("Root Mean Squared Error vs. Periods")
plt.tight_layout()
plt.plot(root_mean_squared_errors)

# Output a table with calibration data.
calibration_data = pd.DataFrame()
calibration_data["predictions"] = pd.Series(predictions)
calibration_data["targets"] = pd.Series(targets)
display.display(calibration_data.describe())

print "Final RMSE (on training data): %0.2f" % root_mean_squared_error

常用超参数

  • steps:是指训练迭代的总次数。一步计算一批样本产生的损失,然后使用该值修改模型的权重一次。
  • batch size:是指单步的样本数量(随机选择)。例如,SGD 的批量大小为 1。

方便变量

periods:控制报告的粒度。例如,如果 periods 设为 7 且 steps 设为 70,则练习将每 10 步(或 7 次)输出一次损失值。与超参数不同,我们不希望您修改 periods 的值。请注意,修改 periods 不会更改您的模型所学习的内容。

合成特征和离群值

  • 合成特征
  • 识别离群值
  • 截取离群值
    离群值设置为相对合理的最小值或最大值来进一步改进模型拟合情况。

过拟合和泛化

以下三项基本假设阐明了泛化:

  • 我们从分布中随机抽取独立同分布 (i.i.d) 的样本。换言之,样本之间不会互相影响。(另一种解释:i.i.d. 是表示变量随机性的一种方式)。
  • 分布是平稳的;即分布在数据集内不会发生变化。
  • 我们从同一分布的数据划分中抽取样本。

拆分数据

  • 训练集 - 用于训练模型的子集。
  • 测试集 - 用于测试训练后模型的子集。

特征工程

过程

  • 映射数值
  • 映射字符串(onehot encoding
  • 映射分类(枚举)值

特点

  • 避免很少使用的离散特征值
  • 最好具有清晰明确的含义
  • 不要将“神奇”的值与实际数据混为一谈(异常值
  • 考虑上游不稳定性

    数据清理

  1. 缩放特征值
    • 帮助梯度下降法更快速地收敛。
    • 帮助避免“NaN 陷阱”。在这种陷阱中,模型中的一个数值变成 NaN(例如,当某个值在训练期间超出浮点精确率限制时),并且模型中的所有其他数值最终也会因数学运算而变成 NaN。
    • 帮助模型为每个特征确定合适的权重。如果没有进行特征缩放,则模型会对范围较大的特征投入过多精力。
  2. 处理极端离群值
    • 对数缩放
    • 限制特征值
  3. 分箱(划分范围
  4. 清查

特征组合(Feature Crosses)

对非线性规律进行编码

特征组合是指通过将两个或多个输入特征相乘来对特征空间中的非线性规律进行编码的合成特征。“cross”(组合)这一术语来自 cross product(向量积)。

组合独热矢量

对独热编码进行特征组合,则会得到可解读为逻辑连接的二元特征

线性学习器可以很好地扩展到大量数据。对大规模数据集使用特征组合是学习高度复杂模型的一种有效策略。


简化正则化 (Regularization for Simplicity):L₂ 正则化

通过降低复杂模型的复杂度来防止过拟合,这种原则称为正则化。
以最小化损失和复杂度为目标,这称为结构风险最小化.

Author: Ykk
Link: https://ykksmile.top/posts/61970/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.