合适的特征应该是具体且可以量化的。漂不漂亮等无法量化,太主观,能否转化为其他具体特征。比如鞋子的颜色、样式等具体的方面。
结构:
分为:
图协议缓冲区
执行(分布式)图的运行时
前者类似于java编译器,后者类似于JVM
学习高级API:tensorflow.estimators
# coding:utf-8
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
city_names = pd.Series(['San Francisco', 'San Jose', 'Sacramento'])
population = pd.Series([852469, 1015785, 485199])
cities = pd.DataFrame({'City name': city_names, 'Population': population})
print()
print(cities.head())
print()
print(type(cities['City name']))
print()
print(cities['City name'])
cities['Area square miles'] = pd.Series([46.87, 176.53, 97.92])
cities['Population density'] = cities['Population'] / cities['Area square miles']
cities['is wide and has saint name'] = (cities['Area square miles'] > 50) & cities['City name'].apply(
lambda name: name.startswith('San'))
print()
print(cities)
cities_1 = cities.reindex([2, 0, 1]) # 索引不变,位置发生变化
print()
print(cities_1.head()) # cities 不变,生成新的DataFrame
# 一般情况下,在开始创建Series和DataFrame的时候,会按照源数据的顺序添加索引
# 索引一旦生成,就永远不会变,索引是稳定的
# 即使数据的排列顺序发生了变化,也不会改变
cities_2 = cities.reindex(np.random.permutation(cities.index))
# pd.set_option('max_columns', 5)
print()
print(cities_2.head())
cities_3 = cities.reindex([2, 3, 4]) # 允许在reinde中添加新的索引,并填充NaN
print()
print(cities_3.head())
#输出:
/Users/tu/PycharmProjects/myFirstPythonDir/venv/bin/python /Users/tu/PycharmProjects/myFirstPythonDir/mytest/numpyDemo/googlepandas.py
City name Population
0 San Francisco 852469
1 San Jose 1015785
2 Sacramento 485199
<class 'pandas.core.series.Series'>
0 San Francisco
1 San Jose
2 Sacramento
Name: City name, dtype: object
City name ... is wide and has saint name
0 San Francisco ... False
1 San Jose ... True
2 Sacramento ... False
[3 rows x 5 columns]
City name ... is wide and has saint name
2 Sacramento ... False
0 San Francisco ... False
1 San Jose ... True
[3 rows x 5 columns]
City name ... is wide and has saint name
0 San Francisco ... False
2 Sacramento ... False
1 San Jose ... True
[3 rows x 5 columns]
City name ... is wide and has saint name
2 Sacramento ... False
3 NaN ... NaN
4 NaN ... NaN
[3 rows x 5 columns]
Process finished with exit code 0
使用tensorflow estimator训练一个预测房价的线性回归模型
将数据集分为训练集和测试集,用训练集训练,测试集评估,根据评估的结果调整超参数,再次用训练集训练,如此反复下去,模型会在测试集上过拟合,测试集也丧失了测试拟合程度的意义。
所以需要再划分:训练集,交叉验证集,测试集
不断用验证集和测试集会导致效果降低。
即,不断地依靠验证集以及之后的测试集的次数越多,最后对于数据是否能泛化到没见过的新数据的信息就越低。
所以需要更多的数据来更新测试集和验证集。
机器学习的调试:
很多时候都是在对数据调试,而不是代码。
- 不随机数据,划分数据集:
- 随机后划分:
测试集、训练集和交叉验证集的分布一定要大致一致。
误差在三个数据集上的表现。
测试数据集链接
代码如下:
import math
from IPython import display
from matplotlib import cm
from matplotlib import gridspec
from matplotlib import pyplot as plt
import os
import numpy as np
import pandas as pd
from sklearn import metrics
import tensorflow as tf
from tensorflow.python.data import Dataset
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
tf.logging.set_verbosity(tf.logging.ERROR) # DEBUG INFO WARN ERROR FATAL
pd.options.display.max_rows = 10
pd.options.display.max_columns = 9
pd.options.display.float_format = '{:.1f}'.format
# 加载数据集
california_housing_dataframe = pd.read_csv("california_housing_train.csv", sep=',')
california_housing_test_dataframe = pd.read_csv("california_housing_test.csv", sep=',')
# 随机数据,很重要的一步
california_housing_dataframe = california_housing_dataframe.reindex(
np.random.permutation(california_housing_dataframe.index))
def process_feature(california_housing_dataframe):
selected_feature = california_housing_dataframe[
["longitude", "latitude", "housing_median_age", "total_rooms", "total_bedrooms", "population", "households",
"median_income"]]
processed_feature = selected_feature.copy()
processed_feature['rooms_per_population'] = processed_feature['total_rooms'] / processed_feature['population']
return processed_feature
def process_target(california_housing_dataframe):
output_target = pd.DataFrame()
output_target['median_house_value'] = california_housing_dataframe['median_house_value'] / 1000.0
return output_target
# 数据被分为训练集、验证集
train_examples = process_feature(california_housing_dataframe.head(12000))
train_targets = process_target(california_housing_dataframe.head(12000))
# print("\n训练集:")
# print(train_examples.describe())
# print(train_targets.describe())
validation_examples = process_feature(california_housing_dataframe.tail(5000))
validation_targets = process_target(california_housing_dataframe.tail(5000))
# print('\n交叉验证集:')
# print(validation_examples.describe())
# print(validation_targets.describe())
#
# print('\n没有测试集')
# 检查数据,绘制经纬度图
# plt.figure(figsize=(13, 8))
#
# ax = plt.subplot(1, 2, 1)
# ax.set_title('Valication Data')
# ax.set_autoscaley_on(False)
# ax.set_ylim([32, 43])
# ax.set_autoscalex_on(False)
# ax.set_xlim([-126, -112])
# plt.scatter(validation_examples['longitude'], validation_examples['latitude'], cmap='coolwarm',
# c=validation_targets['median_house_value'] / validation_targets['median_house_value'].max())
#
# ax = plt.subplot(1, 2, 2)
# ax.set_title('Train Data')
# ax.set_autoscaley_on(False)
# ax.set_ylim([32, 43])
# ax.set_autoscalex_on(False)
# ax.set_xlim(-126, -112)
# plt.scatter(train_examples['longitude'], train_examples['latitude'], cmap='coolwarm',
# c=train_targets['median_house_value'] / train_targets['median_house_value'].max())
test_examples = process_feature(california_housing_test_dataframe)
test_targets = process_target(california_housing_test_dataframe)
# 4.定义输入函数
def my_input_fn(features, targets, batch_size=1, shuffle=True, num_epochs=None):
"""
输入函数
:param features: 输入特征
:param targets: 数据标签
:param batch_size: 输出数据的大小
:param shuffle: 随机抽取数据
:param num_epochs:重复的次数
:return:数据和标签
"""
features = {key: np.array(value) for key, value in dict(features).items()}
ds = Dataset.from_tensor_slices((features, targets)) # 2GB限制
ds = ds.batch(batch_size).repeat(num_epochs)
if shuffle:
ds = ds.shuffle(buffer_size=10000)
features, labels = ds.make_one_shot_iterator().get_next()
return features, labels
def construct_feature_columns(input_features):
return set([tf.feature_column.numeric_column(my_feature) for my_feature in input_features])
def train_model(learning_rate, steps, batch_size, train_examples, train_targets, validation_examples,
validation_targets, test_examples, test_targets, periods=10):
steps_per_periods = steps / periods # 每次报告时所走的步长
# 最优化函数
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=construct_feature_columns(train_examples),
optimizer=my_optimizer)
# 定义输入函数
training_input_fn = lambda: my_input_fn(train_examples, train_targets['median_house_value'], batch_size=batch_size)
prediction_training_input_fn = lambda: my_input_fn(train_examples, train_targets['median_house_value'],
num_epochs=1, shuffle=False)
prediction_validation_input_fn = lambda: my_input_fn(validation_examples, validation_targets['median_house_value'],
num_epochs=1,
shuffle=False)
prediction_test_input_fn = lambda: my_input_fn(test_examples, test_targets['median_house_value'],
num_epochs=1,
shuffle=False)
print('Training model ...')
print('RMSE:')
training_rmse = []
validation_rmse = []
test_rmse = []
for period in range(0, periods):
linear_regressor.train(input_fn=training_input_fn, steps=steps_per_periods)
training_predictions = linear_regressor.predict(input_fn=prediction_training_input_fn)
training_predictions = np.array([item['predictions'][0] for item in training_predictions])
# item是这样的:{'predictions': array([0.015675], dtype=float32)}
validation_predictions = linear_regressor.predict(input_fn=prediction_validation_input_fn)
validation_predictions = np.array([item['predictions'][0] for item in validation_predictions])
test_predictions = linear_regressor.predict(input_fn=prediction_test_input_fn)
test_predictions = np.array([item['predictions'][0] for item in test_predictions])
# 误差
training_root_mean_squared_error = math.sqrt(metrics.mean_squared_error(training_predictions, train_targets))
validation_root_mean_squared_error = math.sqrt(
metrics.mean_squared_error(validation_predictions, validation_targets))
test_root_mean_squared_error = math.sqrt(metrics.mean_squared_error(test_predictions, test_targets))
print('period %02d : %.2f' % (period, training_root_mean_squared_error))
training_rmse.append(training_root_mean_squared_error)
validation_rmse.append(validation_root_mean_squared_error)
test_rmse.append(test_root_mean_squared_error)
print('Model training finished.')
plt.figure()
plt.ylabel('RMSE')
plt.xlabel('Periods')
plt.title('Root mean squared error vs. periods')
plt.tight_layout()
plt.plot(training_rmse, label='training')
plt.plot(validation_rmse, label='validation')
plt.plot(test_rmse, label='test')
plt.legend()
plt.show()
return linear_regressor
train_model(learning_rate=0.00003, steps=5000, batch_size=5, train_examples=train_examples, train_targets=train_targets,
validation_examples=validation_examples, validation_targets=validation_targets, test_examples=test_examples,
test_targets=test_targets, periods=100)
将原始数据转换成特征矢量,叫特征工程。
- 数值型特征直接照搬
- 字符串one hot编码:
- 先对字符串数据整理词汇表,同时有一个词汇表中没有的其他类
- 对词汇表进行one hot编码
即使是少量的异常数据也会破坏掉一个大规模数据集。
将浮点数特征分成离散特征(一个矢量),可以均分,也可以按照分位数分;
这样的样本都从数据集中筛除
- 检查出不良的数据,用直方图、最大值最小值、均值、中位数、标准差。
- 检查离散特征最常见特征值的列表,看是否符合预期。
知道预期的数据状态,并检查手上的数据是否满足预期,或者解释为什么不满足预期,检查训练数据和其他来源的数据是否一致。
相关系数
"""
创建一个集合:用更少的特征取得跟复杂特征效果一样好的成果
特征少,模型使用的资源就少,更加易于维护
"""
import math
from IPython import display
from matplotlib import cm
from matplotlib import gridspec
from matplotlib import pyplot as plt
import os
import numpy as np
import pandas as pd
from sklearn import metrics
import tensorflow as tf
from tensorflow.python.data import Dataset
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
tf.logging.set_verbosity(tf.logging.ERROR) # DEBUG INFO WARN ERROR FATAL
pd.options.display.max_rows = 10
pd.options.display.max_columns = 10
pd.options.display.float_format = '{:.1f}'.format
# 加载数据集
california_housing_dataframe = pd.read_csv("california_housing_train.csv", sep=',')
california_housing_test_dataframe = pd.read_csv("california_housing_test.csv", sep=',')
# 随机数据,很重要的一步
california_housing_dataframe = california_housing_dataframe.reindex(
np.random.permutation(california_housing_dataframe.index))
def process_feature(california_housing_dataframe):
selected_feature = california_housing_dataframe[
["longitude", "latitude", "housing_median_age", "total_rooms", "total_bedrooms", "population", "households",
"median_income"]]
processed_feature = selected_feature.copy()
processed_feature['rooms_per_population'] = processed_feature['total_rooms'] / processed_feature['population']
return processed_feature
def process_target(california_housing_dataframe):
output_target = pd.DataFrame()
output_target['median_house_value'] = california_housing_dataframe['median_house_value'] / 1000.0
return output_target
# 数据被分为训练集、验证集
train_examples = process_feature(california_housing_dataframe.head(12000))
train_targets = process_target(california_housing_dataframe.head(12000))
print("\n训练集:")
display.display(train_examples.describe())
print("\n训练集标签:")
display.display(train_targets.describe())
validation_examples = process_feature(california_housing_dataframe.tail(5000))
validation_targets = process_target(california_housing_dataframe.tail(5000))
print('\n交叉验证集:')
display.display(validation_examples.describe())
print("\n交叉验证集标签:")
display.display(validation_targets.describe())
test_examples = process_feature(california_housing_test_dataframe)
test_targets = process_target(california_housing_test_dataframe)
print('\n测试集:')
display.display(test_examples.describe())
print("\n测试集标签:")
display.display(test_targets.describe())
# 检查数据,绘制经纬度图
# plt.figure(figsize=(13, 8))
#
# ax = plt.subplot(1, 3, 1)
# ax.set_title('Valication Data')
# ax.set_autoscaley_on(False)
# ax.set_ylim([32, 43])
# ax.set_autoscalex_on(False)
# ax.set_xlim([-126, -112])
# plt.scatter(validation_examples['longitude'], validation_examples['latitude'], cmap='coolwarm',
# c=validation_targets['median_house_value'] / validation_targets['median_house_value'].max())
#
# ax = plt.subplot(1, 3, 2)
# ax.set_title('Train Data')
# ax.set_autoscaley_on(False)
# ax.set_ylim([32, 43])
# ax.set_autoscalex_on(False)
# ax.set_xlim(-126, -112)
# plt.scatter(train_examples['longitude'], train_examples['latitude'], cmap='coolwarm',
# c=train_targets['median_house_value'] / train_targets['median_house_value'].max())
#
# ax = plt.subplot(1, 3, 3)
# ax.set_title('Test Data')
# ax.set_autoscaley_on(False)
# ax.set_ylim([32, 43])
# ax.set_autoscalex_on(False)
# ax.set_xlim(-126, -112)
# plt.scatter(test_examples['longitude'], test_examples['latitude'], cmap='coolwarm',
# c=test_targets['median_house_value'] / test_targets['median_house_value'].max())
#
# plt.show()
"""
构建良好的特征集
用相关矩阵,找出原始特征之间的相关性
要有与目标有相关性的特征,也要有独立的特征;
"""
correlation_dataframe = train_examples.copy()
correlation_dataframe['target'] = train_targets.copy()
correlation_metrix = correlation_dataframe.corr()
print("\n相关矩阵:")
display.display(correlation_metrix)
'''
longitude latitude 负相关 -0.9
total_rooms total_bedrooms population households 正向关 0.9 1.0
median_income target 正向关 0.7;即与目标相关的特征为median_income
根据相关矩阵,合成特征,移除特征,
'''
# 4.定义输入函数
def my_input_fn(features, targets, batch_size=1, shuffle=True, num_epochs=None):
"""
输入函数
:param features: 输入特征
:param targets: 数据标签
:param batch_size: 输出数据的大小
:param shuffle: 随机抽取数据
:param num_epochs:重复的次数
:return:数据和标签
"""
features = {key: np.array(value) for key, value in dict(features).items()}
ds = Dataset.from_tensor_slices((features, targets)) # 2GB限制
ds = ds.batch(batch_size).repeat(num_epochs)
if shuffle:
ds = ds.shuffle(buffer_size=10000)
features, labels = ds.make_one_shot_iterator().get_next()
return features, labels
def construct_feature_columns(input_features):
return set([tf.feature_column.numeric_column(my_feature) for my_feature in input_features])
def train_model(learning_rate, steps, batch_size, train_examples, train_targets, validation_examples,
validation_targets, test_examples, test_targets, periods=10):
steps_per_periods = steps / periods # 每次报告时所走的步长
# 最优化函数
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=construct_feature_columns(train_examples),
optimizer=my_optimizer)
# 定义输入函数
training_input_fn = lambda: my_input_fn(train_examples, train_targets['median_house_value'], batch_size=batch_size)
prediction_training_input_fn = lambda: my_input_fn(train_examples, train_targets['median_house_value'],
num_epochs=1, shuffle=False)
prediction_validation_input_fn = lambda: my_input_fn(validation_examples, validation_targets['median_house_value'],
num_epochs=1,
shuffle=False)
prediction_test_input_fn = lambda: my_input_fn(test_examples, test_targets['median_house_value'],
num_epochs=1,
shuffle=False)
print('Training model ...')
print('RMSE:')
training_rmse = []
validation_rmse = []
test_rmse = []
for period in range(0, periods):
linear_regressor.train(input_fn=training_input_fn, steps=steps_per_periods)
training_predictions = linear_regressor.predict(input_fn=prediction_training_input_fn)
training_predictions = np.array([item['predictions'][0] for item in training_predictions])
# item是这样的:{'predictions': array([0.015675], dtype=float32)}
validation_predictions = linear_regressor.predict(input_fn=prediction_validation_input_fn)
validation_predictions = np.array([item['predictions'][0] for item in validation_predictions])
test_predictions = linear_regressor.predict(input_fn=prediction_test_input_fn)
test_predictions = np.array([item['predictions'][0] for item in test_predictions])
# 误差
training_root_mean_squared_error = math.sqrt(metrics.mean_squared_error(training_predictions, train_targets))
validation_root_mean_squared_error = math.sqrt(
metrics.mean_squared_error(validation_predictions, validation_targets))
test_root_mean_squared_error = math.sqrt(metrics.mean_squared_error(test_predictions, test_targets))
print('period %02d : %.2f' % (period, training_root_mean_squared_error))
training_rmse.append(training_root_mean_squared_error)
validation_rmse.append(validation_root_mean_squared_error)
test_rmse.append(test_root_mean_squared_error)
print('Model training finished.')
plt.figure()
plt.ylabel('RMSE')
plt.xlabel('Periods')
plt.title('Root mean squared error vs. periods')
plt.tight_layout()
plt.plot(training_rmse, label='training')
plt.plot(validation_rmse, label='validation')
plt.plot(test_rmse, label='test')
plt.legend()
plt.show()
return linear_regressor
'''
longitude latitude 负相关 -0.9
total_rooms total_bedrooms population households 正向关 0.9 ~ 1.0
median_income target 正向关 0.7;即与目标相关的特征为median_income
housing_median_age 与 total_rooms total_bedrooms population households 负相关 -0.3 ~ -0.4
根据相关矩阵,合成特征,移除特征,
'''
# minimal_features = ["latitude", "median_income"]
#
# assert minimal_features, "至少必须有一个特征"
#
# minimal_features_train_examples = train_examples[minimal_features]
# minimal_features_validation_examples = validation_examples[minimal_features]
# minimal_features_test_examples = test_examples[minimal_features]
# plt.scatter(train_examples["latitude"], train_targets['median_house_value'])
# plt.show()
# 分桶
def select_and_transform_features(source_df):
LATITUDE_RANGES = zip(range(32, 42), range(33, 43))
selected_examples = pd.DataFrame()
selected_examples['median_income'] = source_df['median_income'].copy()
for r in LATITUDE_RANGES:
selected_examples['latitude_%d_%d' % r] = source_df['latitude'].apply(
lambda l: 1 if r[0] <= l < r[1] else 0)
return selected_examples
selected_train_examples = select_and_transform_features(train_examples)
selected_validation_examples = select_and_transform_features(validation_examples)
selected_test_examples = select_and_transform_features(test_examples)
# 减少特征后,学习率降低,运算负担减轻
train_model(learning_rate=0.1, steps=2000, batch_size=5, train_examples=selected_train_examples,
train_targets=train_targets,
validation_examples=selected_validation_examples, validation_targets=validation_targets,
test_examples=selected_test_examples,
test_targets=test_targets, periods=20)
用特征组合+大数据是学习复杂模型的有效策略
神经网络是另外一种策略
组合特征在这里可以理解为就是多项式回归的一些项。区别于线性回归的项。
叫做逻辑连接
特征组合本质上可以表达更加丰富准确的信息。
特征组合可以使得线性回归模型可以拟合非线性数据。
FTRL优化算法
my_optimizer = tf.train.FtrlOptimizer(learning_rate=learning_rate)
将离散特征(字符串、枚举、整数)进行one hot 编码
可以将连续特征分桶,进而one hot编码
对全部特征进行分桶的结果:
# 基于分位数的分桶
def get_quantile_based_boundaries(feature_values, num_buckets):
boundaries = np.arange(1.0, num_buckets) / num_buckets
quantile = feature_values.quantile(boundaries) # Series
return [quantile[q] for q in quantile.keys()] # list
def construct_feature_columns():
households = tf.feature_column.numeric_column('households')
longitude = tf.feature_column.numeric_column('longitude')
latitude = tf.feature_column.numeric_column('latitude')
housing_median_age = tf.feature_column.numeric_column('housing_median_age')
total_rooms = tf.feature_column.numeric_column('total_rooms')
total_bedrooms = tf.feature_column.numeric_column('total_bedrooms')
population = tf.feature_column.numeric_column('population')
median_income = tf.feature_column.numeric_column('median_income')
rooms_per_population = tf.feature_column.numeric_column('rooms_per_population')
bucketized_households = tf.feature_column.bucketized_column(households, get_quantile_based_boundaries(
train_examples["households"], 7)) # households分为7个桶
bucketized_longitude = tf.feature_column.bucketized_column(longitude, get_quantile_based_boundaries(
train_examples['longitude'], 10)) # longitude分为10个桶
bucketized_latitude = tf.feature_column.bucketized_column(latitude, get_quantile_based_boundaries(
train_examples["latitude"], 10))
bucketized_housing_median_age = tf.feature_column.bucketized_column(housing_median_age,
get_quantile_based_boundaries(
california_housing_dataframe[
"housing_median_age"], 10))
bucketized_total_rooms = tf.feature_column.bucketized_column(total_rooms, get_quantile_based_boundaries(
train_examples["total_rooms"], 10))
bucketized_total_bedrooms = tf.feature_column.bucketized_column(total_bedrooms, get_quantile_based_boundaries(
train_examples["total_bedrooms"], 10))
bucketized_population = tf.feature_column.bucketized_column(population, get_quantile_based_boundaries(
train_examples["population"], 10))
bucketized_median_income = tf.feature_column.bucketized_column(median_income, get_quantile_based_boundaries(
train_examples["median_income"], 10))
bucketized_rooms_per_population = tf.feature_column.bucketized_column(rooms_per_population,
get_quantile_based_boundaries(
train_examples["rooms_per_population"],
10))
feature_columns = {bucketized_households,
bucketized_longitude,
bucketized_latitude,
bucketized_housing_median_age,
bucketized_total_rooms,
bucketized_total_bedrooms,
bucketized_population,
bucketized_median_income,
bucketized_rooms_per_population}
return feature_columns
又叫特征交叉
对连续数据离散化(分桶),之后进行特征组合。
在特征组合之后,对模型仍需要提供原始特征,原始特征可以帮助模型区分包含不同特征交叉的hash存储区域内容
long_x_lat = tf.feature_column.crossed_column(keys=[bucketized_longitude, bucketized_latitude],
hash_bucket_size=1000)
feature_columns = {bucketized_households,
bucketized_longitude,
bucketized_latitude,
bucketized_housing_median_age,
bucketized_total_rooms,
bucketized_total_bedrooms,
bucketized_population,
bucketized_median_income,
bucketized_rooms_per_population,
long_x_lat}
正则化用来解决过拟合问题,过拟合如下所示:
为了防止过拟合,不光要考虑模型的损失,也要考虑模型的复杂度。
L2正则化项和正则化率 λ λ
λ λ 小,容易过拟合
λ λ 大,容易欠拟合
L2正则化对模型的影响:
- 使得权重接近于0
- 使得权重平均值接近于0
- 使得权重呈正态分布
逻辑回归会不断的促使损失趋近于0;所以必须进行:
L2正则化
早停法,限制训练的步数或学习速率
逻辑回归输出的是概率。
所以要设置阈值进行分类。
分类会涉及到一些指标:
实 | 际 | |
---|---|---|
真正例 | 假正例 | |
预 | 预测狼要来——>狼来了 | 预测狼要来——>狼没来 |
测 | 假负例 | 真负例 |
没预警,结果狼来了 | 没预警,狼也没来 |
即:
TP | FP |
---|---|
FN | TN |
AUC
Area under curve:曲线下面积
ROC曲线下面积表示随机正例样本位于随机负例右侧的概率
即,随机的给出一个正样本,一个负样本,分类器将正样本识别为正样本的概率大于将负样本识别为正样本的概率的概率;
AUC越大,分类的效果越好;
如果AUC达到了1,很有可能不是你的模型无敌,而是你错了,检查一下是否过拟合、是否将label作为feature等情况。
预测偏差
预测偏差 = 预测平均值 - 数据集的标签的实际平均值
比如,我们知道垃圾邮件在邮件中出现的概率是1%,如果模型预测的结果是垃圾邮件在邮件中出现的概率是30%,那么这个模型存在较大的预测偏差。
造成的原因可能有:
一种办法是给已经训练好的模型加校准层,但:
(1)校准层治标不治本,还是不知道出问题的原因
(2)使得系统更加复杂,也更加脆弱。
逻辑回归
linear_classifier=tf.estimator.LinearClassifier(feature_columns=construct_feature_columns(training_examples),
optimizer=my_optimizer)
正则化有L0正则化,L1正则化,L2正则化。
L2正则化解决过拟合的问题。
L1正则化解决稀疏特征的问题。
如果模型包含大量的稀疏矢量,同时这些稀疏特征进行特征组合,会耗费很大的计算资源。如果能将高维度稀疏特征的权重降为0,就可以节省资源。
L2正则化可以降低权重。
L1正则化可以使得模型中信息缺失的权重正好为0。
离线训练 | 在线训练 |
---|---|
容易构建、测试:可批量训练、批量测试,不断迭代可以达到很好的效果 | 可以随着时间的推移不断的为训练数据添加新的数据,可以定期同步更新到最新版本; 使用渐进式验证,不是批量训练和批量测试 |
模型容易过时 | 可以根据变化进行调整,不会过时 |
也需要对输入进行监控 | 需要监控、模型回滚、数据隔离功能 |
离线推理和在线推理都是在线下用数据进行训练,只不过在对新数据进行预测的时候,离线推理是攒一波数据用模型一次预测完存储到表里边,之后线上来的数据直接通过表查询预测的结果,所以如果表里边没有这个数据,那就没有办法预测,但是它对资源的需求低。
在线预测就是来一个线上的数据,我就预测一次,再给线上返回结果。即把训练好的模型放到服务器。所以避免了线上数据没有预测结果的情况。但是耗费资源。
现在流行的是在线学习。模型的训练过程也搬到了线上,线上学习,线上预测。
离线推理:
- 优点:
- 推理成本低
- 可以使用批量方法
- 可以在推送之前对预测进行后期验证
- 缺点:
- 只能对知道的数据进行预测,不适用于存在长尾的情况
- 更新会延迟数小时或者数天
在线推理:
- 优点:
- 适合长尾
- 缺点:
- 计算量大,对延迟敏感,故而限制模型的复杂度
- 监控需求多
现在都是用在线学习
离线推理和在线推理都有不可避免的缺点,但在线学习的实现难度最大。
数据对我们的重要性就是传统软件开发中代码对程序员的重要性。
但没有对于数据的单元测试。
模型的好坏取决于输入特征的数据。数据变了,模型也会跟着变。
要不断的测试数据、验证数据、监控数据。
比如:需要移除掉不用或者很少使用的特征。如果一个特征对模型帮助很小,这个特征的输入数据发生了巨变,那么可能会影响到模型。
- 可靠性:
- 数据一直都可以用吗?来源可靠不?(某些数据是不是来自于崩溃的服务器)
版本控制
必要性
相关性
反馈环
癌症预测
在癌症预测模型的特征中,含有医院名称,而医院名称和是否患有癌症具有微妙的关系。比如一家肿瘤医院的患者有很大的概率患有癌症。所以模型对这个特征有了很大的权重。
但是在预测新的病人是否患有癌症的时候,缺无法利用此特征。这是很失败的。