第二篇 端到端的机器学习

一、 机器学习项目清单

完成机器学习主要有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))

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,049评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,478评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,109评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,097评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,115评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,280评论 1 279
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,748评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,398评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,553评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,440评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,487评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,176评论 3 317
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,750评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,821评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,049评论 1 257
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,559评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,150评论 2 341

推荐阅读更多精彩内容