一、 机器学习项目清单
完成机器学习主要有8步:
1.架构问题,关注蓝图。
1) 用商业术语定义目标。
2) 方案如何使用?
3) 目前的解决方案/办法是什么?
4) 应该如何架构问题(有监督/无监督,在线/离线,等等)?
5) 如何测量性能?
6) 性能指标是否与业务目标一致?
7) 每个业务目标需要的最低性能是什么?
8) 有没有一些相似的问题?能重用一些经验和工具吗?
9) 有没有相关有经验的人?
10) 如何手动解决此问题?
11) 列出目前为止你(或其他人) 的假设。
12) 如果可能的话, 验证假设。
2.获取数据。
注意: 尽可能的自动化, 以便获取最新数据。
1) 列出需要的数据及其体量。
2) 查找并记录获取数据的途径。
3) 检查需要的空间。
4) 检查法律义务, 必要时获取授权。
5) 获取访问权限。
6) 创建工作空间(确保具有足够的存储空间) 。
7) 获取数据。
8) 将数据转换为可操作的格式(不改变数据本身) 。
9) 确保删除或保护敏感信息(例如, 匿名) 。
10) 检查数据的类型和大小(时间序列、 样本、 地点等) 。
11) 采样一个测试数据集, 放在一边, 永远不要用它(没有数据窥视! ) 。
3.研究数据以获取灵感。
1)创建数据的副本用于研究(如果需要, 可以将其抽样为可管理的大小) 。
2)创建一个Jupyter笔记本来记录数据研究。
3)研究每个属性及其特征:
名字;·类型(分类、整型/浮点型、有界/无界、文本、结构等);缺失值的百分比;噪音和噪音类型(随机、异常、舍入误差等);·可能有用的任务?分布类型(高斯、统一、对数等)
4)对于有监督的学习任务,确认目标属性。
5)可视化数据。
6)研究属性之间的相关性。
7)研究如何手动解决问题。
8)确定希望使用转换。
9)确定可能有用的额外数据(回到之前的“获取数据”部分)。
10)记录学习到的东西。
4.准备数据以更好地将低层模型暴露给机器学习算法。
1).数据清理:
·修复或删除异常值(可选) 。
·填充缺失值(例如, 使用零、 平均数、 中位数等) 或删除该行(或列) 。
2).特征选择(可选) :
·删除不能为任务提供任何有用信息的属性。
3).在适当情况下, 处理特征:
·离散连续特征。
·分解特征(如, 分类、 日期/时间等) 。
·添加期望的特征转换(如, log(x) 、 sqrt(x) 、 x2等) 。
·聚合特征称为期望的新特征。
注意:
1)·在数据的副本上工作(保持原始数据集不变)。
2)·编写适用于所有数据转换的函数,原因有五个:
A·可以很容易地准备下一次得到新数据时的数据。
B·可以在未来的项目中使用这些转换。
C·清理和准备测试数据集。
D·一旦解决方案失效,用来清理和准备新数据实例。
E·可以轻松地将你的准备选择作为超参数。
5.研究各种不同的模型,并列出最好的模型。
1).使用标准参数, 从不同类别(例如, 线性、 朴素贝叶斯、SVM、 随机森林、 神经网络等) 中训练需求快速的不成熟的模型。
2).测量并比较它们的性能。
·对于每个模型, 使用N倍交叉验证并计算N次折叠的性能测试的均值和标准差。
3).分析每个算法最重要的变量。
4).分析模型产生的错误类型。
人类用什么样的数据避免这些错误?
5).快速进行特征选择和处理。
6).对前面五步进行一两次快速迭代。
7).列出前三到五个最有希望的模型,倾向于选择有不同错误类型的模型。
6.微调模型,并将其组合为更好的解决方案。
1).使用交叉验证微调超参数。
·把数据转换选择当作超参数,尤其是不确定时(例如,应该用零或者平均值填充缺失值吗?或者直接删除它?)。
·除非需要研究的超参数值很少,否则更喜欢在网格搜索上随机搜索。如果训练很长,你可能更喜欢贝叶斯优化方法(例如,如Jasper Snoek、 Hugo Larochelle和Ryan Adams所述,使用高斯过程进行先验
2).尝试组合方法。组合多个好模型往往比单独运行效果好。
3).一旦你对最终模型有信心,在测试集上测量它的性能以估计泛化误差。
注意:测量泛化误差后,不要调整模型:只需要开始过度拟合测试集
7.提出解决方案。
1).文档化你所做的工作。
2).创建完美的演示。
首先确保突出蓝图。
3).解释为什么你的解决方案达到了业务目标。
4).不要忘记展示你发现的一些有趣的地方。
·描述什么可以工作, 什么不行。
·列出你的假设和系统的局限。
5).确保你的关键发现被完美展示或易于记忆的陈述。
8.启动、监视、维护系统。
1).准备好生产环境的解决方案(插入生产数据输入, 写单元测试等) 。
2).编写监控代码, 定期检查系统的性能, 出问题时及时报警。
·同样需要考虑缓慢退化: 随着数据的增加, 模型往往会“腐烂”。
·测量性能可能需要人工流水线(例如, 众包服务) 。
·同时监控输入质量(例如, 发送随机值的故障传感器, 或其他团队的输出过时) 。 这对在线学习系统尤为重要。
3).定期对新数据重新建模(尽可能自动化) 。
二 开始建立开发模型
使用加州人口普查的数据建立起加州的房价模型。 数据中有许多指标, 诸如每个街区的人口数量、 收入中位数、 房价中位数等。 街区是美国人口普查局发布样本数据的最小地理单位;
模型需要从这个数据中学习, 从而能够根据所有其他指标,预测任意区域的房价中位数;
根据上述的机器学习项目清单,开始机器学习的搭建
2.1 框架

一个序列的数据处理组件称为一个数据流水线(Pipeline)。流水线在机器学习系统中非常普遍,因为需要大量的数据操作和数据转化才能应用。
组件通常是异步运行。每个组件拉取大量的数据,然后进行处理,再将结果传输给另一个数据仓库;一段时间之后,流水线中的下一个组件会拉取前面的数据,并给出自己的输出,以此类推。组件和组件之间的连接只有数据仓库。
要向老板询问当前的解决方案(如果有的话)。你可以将其当作参考,也能从中获得解决问题的洞察。
有了这些信息, 你现在可以开始设计系统了。 首先, 你需要回答框架问题: 是监督式? 还是无监督式? 又或者是强化学习? 是分类任务、 回归任务还是其他任务? 应该使用批量学习还是在线学习技术?
显然, 这是一个典型的监督式学习任务, 因为已经给出了标记的训练示例(每个实例都有预期的产出,也就是该地区的房价中位数);这是一个多变量回归问题,因为系统要使用多个特征进行预测(使用到区域的人口、 收入中位等)
2.2 选择性能指标
接下来是要选择一个性能衡量指标。 回归问题的典型性能衡量指标是均方根误差(RMSE,root mean square error) , 它测量的是预测过程中, 预测错误的标准偏差

参数:
m--测量RMSE时,所使用的数据集中实例的数量。
X(i)---是数据集中,第i个实例的所有特征值的向量
y(i) ---是标签(也就是我们期待该实例的输出值)
例如,如果数据集的第一个区域位于经度-118.29°,纬度33.91°,居民数量为1416,平均收入为38372美元,房价中位数为156400美元(暂且忽略其他特征)


X是数据集中所有实例的所有特征值的矩阵(标记特征除外)。每个实例为一行,也就是说,第i行等于x(i) 的转置矩阵,记作(x(i) ) T

h是系统的预测函数, 也称为一个假设。 当给定系统一个实例的特征向量x(i) , 它会输出一个预测值ŷ(i) = h(x(i)) ( 读作“y-hat”)
例如, 如果系统预测第一个区域的房价中位数为158400美元,则ŷ(1) = h(x(1)) = 158,400。 该区域的预测误差为 ŷ(1) – y(1) = 2,000 =2000。
RMSE(X, h) 是使用假设h在示例上测量的成本函数;
我们使用小写的斜体字体表示标量值(例如m和y(i) ) 和函数名(例如h) , 小写黑体字表示向量(例如x(i) ) , 大写黑体字表示矩阵(例如X)
RMSE通常是回归任务的首选性能衡量指标, 但在某些情况下, 其他函数可能会更适合。

均方根误差和平均绝对误差两种方法都是测量两个向量之间的距离:预测向量和目标值向量。距离或者范数的测度可能有多种:
1)计算平方和的根(RMSE)对应欧几里得范数:
计算距离概念。也称之为 范数,记作L2 ,

(或者||·||)。
2)计算绝对值的总和(MAE)对应L1 范数,记作

。有时它也被称为曼哈顿距离,因为它在测量一个城市的两点之间的距离时,只能沿着正交的城市街区行走。
范数指数越高,则越关注大的价值,忽视小的价值。这就是为什么RMSE比MAE对异常值更敏感。但是当异常值非常稀少(例如钟形曲线)时,RMSE的表现优异,通常作为首选。
2.3 检查假设
在开始机器学习编程前一定要确定机器学习的框架,例如,确定下游组件利用当前组件的价格,只是需要确定房价是什么区间(昂贵、廉价等),而不需要确定具体的价格,则我们就不能使用回归算法;
三 、开发
3.1 获取数据:housing.csv

3.2 准备python库
我们需要Pandas、 NumPy、Matplotlib以及Scikit-Learn库
A:没有数据的朋友,通过调用该函数从网络上下载数据
import os
import requests
BASE_URL='https://raw.githubusercontent.com/ageron/handson-ml/master/'
BASE_PATH='datasets/housing'
def download_file(xurl=BASE_URL,xpath=BASE_PATH):
headers = {
"Host":'img31.mtime.cn',
"User-Agent":'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:53.0) Gecko/20100101 Firefox/53.0',
"Accept":'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
"Accept-Language":'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
"Accept-Encoding":'gzip, deflate',
"Connection":'keep-alive',
"Upgrade-Insecure-Requests":"1"}
if not os.path.isdir(xpath):
os.makedirs(xpath)
tfile='housing.tgz'
tpath=os.path.join(xpath,tfile)
res=requests.get(url=xurl+tpath,headers=headers)
with open(tpath,"wb") as fp:
fp.write(res.content)
B:解压下载的文件,使用pandas读取文件,返回DataFrame
def load_data(fname='housing.csv'):
mpath=os.path.join(BASE_PATH,fname)
mfile=pd.read_csv(mpath)
return mfile
C: 解析DataFrame
c.1 head方法返回指定的行的数据
xheader=load_data().head(6)
返回前6行数据;
c.2 info()方法
DataFrame对象的info方法,返回数据集的摘要信息
x=load_data().info()
print(x)
打印结果:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 20640 entries, 0 to 20639
Data columns (total 10 columns):
longitude 20640 non-null float64
latitude 20640 non-null float64
housing_median_age 20640 non-null float64
total_rooms 20640 non-null float64
total_bedrooms 20433 non-null float64
population 20640 non-null float64
households 20640 non-null float64
median_income 20640 non-null float64
median_house_value 20640 non-null float64
ocean_proximity 20640 non-null object
dtypes: float64(9), object(1)
memory usage: 1.6+ MB
None
从这个信息可以查看总行数、 每个属性的类型和非空值的数量
c.3 value_counts()按值进行统计
mdf=load_data()
mdf['ocean_proximity'].value_counts()
显示结果:
<1H OCEAN 9136
INLAND 6551
NEAR OCEAN 2658
NEAR BAY 2290
ISLAND 5
Name: ocean_proximity, dtype: int64
c.4 describe数值属性摘要
mdf=load_data()
x=mdf.describe()
返回结果:
按每一个列显示的信息
longitude ... median_house_value
count 20640.000000 ... 20640.000000
mean -119.569704 ... 206855.816909
std 2.003532 ... 115395.615874
min -124.350000 ... 14999.000000
25% -121.800000 ... 119600.000000
50% -118.490000 ... 179700.000000
75% -118.010000 ... 264725.000000
max -114.310000 ... 500001.000000
[8 rows x 9 columns]
分析:
std行显示的是标准差(用来测量数值的离散程度);25%、 50%和75%行显示相应的百分位数
c.5 DataFrame对象的hist方法
一种快速了解数据类型的方法是绘制每个数值属性的直方图。直方图用来显示给定值范围(横轴) 的实例数量(纵轴) 。 你可以一次绘制一个属性, 也可以在整个数据集上调用hist() 方法, 绘制每个属性的直方图
import pandasas pd
import matplotlib.pyplotas plt
mdf=load_data()
mdf.hist(bins=50,figsize=(20,15))
plt.show()
#hist函数参数:
bins--指定箱子的个数,表示一共有几个直方图;
figsize--表示图像大小的元组
统计结果(显示每个属性的统计直方图):

4. 创建测试集
4.1 使用python方式
测试数据集通常是数据集的20%
#创建测试集合
def get_train(data,rat):
# [ 7034 16749 13078 ... 2282 9196 18362]
sd=np.random.permutation(len(data))
size=int(len(data)*rat)
train_data=sd[:size]
m_data=sd[size:]
# iloc主要使用数字来索引数据,而不能使用字符型的标签来索引数据。
return data.iloc[train_data],data.iloc[m_data]
4.2 根据每个实例的hash值获取测试数据集
# 得到测试集合和训练集
def m_rate(xid,m_rate,hash=hashlib.md5):
# hash.digest()
# 返回摘要,作为二进制数据字符串值
return hash(np.int64(xid)).digest()[-1]<256*m_rate
def m_getdate(m_data):
m_id = m_data['index']# 返回Series类型
m_temp=m_id.apply(lambda ob:m_rate(ob,0.2))
return m_data.loc[~m_temp],m_data.loc[m_temp]
# 返回带有索引的DataFrame对象
m_data=load_data().reset_index()
m_train,m_test=m_getdate(m_data)
这种方式,要确保数据集不能随意删除记录,否则行的标识数字不能保持连续状态;
4.3 sk-learn居然这么简单,服了
from sklearn.model_selectionimport train_test_split
m_data=load_data()
m_train,m_test=train_test_split(m_data,test_size=0.2,random_state=42)
print(len(m_train),len(m_test))
网友评论