机器学习 - 01章

前言

本案例来源于 Github, ageron / handson-ml,目前正在借助该项目熟悉 numpy, pandas, matplotlib 的用法。

项目为英文,我将根据我的进度逐步翻译,并在代码中加上自己的注释,以供学习和回顾。每当我翻译完一章后,我将提交 notebook 的代码, 届时将会放出仓库地址。


第 1 章 - 机器学习概览

这些代码用于生成第1章的一些图表。


配置

首先,让我们看看此 notebook 能否兼容 python2 和 python3 环境,通过导入几个常用的模块,确保 MatplotLib 以内联的方式绘图,然后准备一个函数来保存图表:

# 引入以下模块以同时兼容 python2 和 python3
from __future__ import division, print_function, unicode_literals

# 引入常用模块
import numpy as np
import os

# 确保此 notebook 稳定运行
np.random.seed(42)

# 设置绘图格式
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
plt.rcParams['axes.labelsize'] = 14
plt.rcParams['xtick.labelsize'] = 12
plt.rcParams['ytick.labelsize'] = 12

# 保存图表
PROJECT_ROOT_DIR = '.'
CHAPTER_ID = 'fundamentals'

def save_fig(fig_id, tight_layout=True):
    path = os.path.join(PROJECT_ROOT_DIR, 'images', CHAPTER_ID, fig_id + '.png')
    print('Saving figure', fig_id)
    if tight_layout:
        plt.tight_layout()
    plt.savefig(path, format='png', dpi=300)

# 忽略无用的警告信息
import warnings
warnings.filterwarnings(action='ignore', module='scipy', message='^internal gelsd')

例 1-1

此函数只用作合并 datasets/lifesat/oecd_bli_2015.csvdatasets/lifesat/gdp_per_captita.csv 中的数据。这将会冗长而繁琐,并且这并不属于机器学习,这也是我没将它写进书中的原因。

本书中代码用到的数据文件在当前目录中,我只是对它进行了调整,来获取 datasets/lifesat

# 清洗数据 (本章后续会详细介绍)
def prepare_country_stats(oecd_bli, gdp_per_capita):
    oecd_bli = oecd_bli[oecd_bli['INEQUALITY'] == 'TOT']
    oecd_bli = oecd_bli.pivot(index='Country', columns='Indicator', values='Value')

    gdp_per_capita.rename(columns={'2015': 'GDP per capita'}, inplace=True)
    gdp_per_capita.set_index('Country', inplace=True)
    full_country_stats = pd.merge(left=oecd_bli, left_index=True, right=gdp_per_capita, right_index=True)
    full_country_stats.sort_values(by='GDP per capita', inplace=True)

    remove_indices = [0, 1, 6, 8, 33, 34, 35]
    keep_indices = list(set(range(36)) - set(remove_indices))

    return full_country_stats[['GDP per capita', 'Life satisfaction']].iloc[keep_indices]
import os

# 设置数据的储存路径
datapath = os.path.join('datasets', 'lifesat', '')
# 例子
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import sklearn.linear_model

# 加载数据
oecd_bli = pd.read_csv(datapath + 'oecd_bli_2015.csv', thousands=',')
gdp_per_capita = pd.read_csv(datapath + 'gdp_per_capita.csv', thousands=',', delimiter='\t', encoding='latin1', na_values='n/a')

# 清洗数据
country_stats = prepare_country_stats(oecd_bli, gdp_per_capita)

# 合并数据
# np.r_是按列连接两个矩阵, 要求列数相等
# np.c_是按行连接两个矩阵, 要求行数相等
x = np.c_[country_stats['GDP per capita']]
y = np.c_[country_stats['Life satisfaction']]

# 可视化数据
country_stats.plot(kind='scatter', x='GDP per capita', y='Life satisfaction')
plt.show()

# 创建线型模型
model = sklearn.linear_model.LinearRegression()

# 训练模型
model.fit(x, y)

# 预测塞浦路斯地区的情况
x_new = [[22587]]
print(model.predict(x_new))
塞浦路斯

[[5.96242338]]


注: 你可以忽略此 notebook 剩下的部分,那些只是生成一些本章的图表


加载并清洗 Life satisfaction 数据

如果你愿意,你可以从 OECD 的网站获取最新数据。从 http://stats.oecd.org/index.aspx?DataSetCode=BLI 下载 CSV 文件,然后保存到 datasets/lifesat/ 中。

# 从 csv 文件读取数据, 以逗号为分隔符
oecd_bli = pd.read_csv(datapath + 'oecd_bli_2015.csv', thousands=',')

# 提取出 INEQUALITY 字段为 'TOT' 的数据
oecd_bli = oecd_bli[oecd_bli['INEQUALITY'] == 'TOT']

# 转换为以国家为索引
oecd_bli = oecd_bli.pivot(index='Country', columns='Indicator', values='Value')

# 展示前两行数据
oecd_bli.head(2)
oecd_bli.head(2)
# head() 默认展示前 5 行数据
oecd_bli['Life satisfaction'].head()
oecd_bli['Life satisfaction'].head()

加载并清洗 GDP per capita 数据

如上所述,如果你愿意,你可以更新 GDP per capita 数据。从 http://goo.gl/j1MSKe(=> imf.org) 下载最新数据,然后保存到 datasets/lifesat/ 中。(国内自备梯子)

# 读取数据
gdp_per_capita = pd.read_csv(datapath+'gdp_per_capita.csv', thousands=',', delimiter='\t', encoding='latin1', na_values="n/a")

# 更改 "2015" 字段名称为 "GDP per capita"
gdp_per_capita.rename(columns={'2015': 'GDP per capita'}, inplace=True)

# 将索引设为 "Country"
gdp_per_capita.set_index("Country", inplace=True)

gdp_per_capita.head(2)
gdp_per_capita.head(2)
# 合并数据集
full_country_stats = pd.merge(left=oecd_bli, left_index=True, right=gdp_per_capita, right_index=True)

# 根据 "GDP per capita" 排序
full_country_stats.sort_values(by='GDP per capita', inplace=True)

full_country_stats.head(2)
full_country_stats.head(2)
# 查询 "United States" 的 "GDP per capita" 和 "Life satisfaction"
full_country_stats[['GDP per capita', 'Life satisfaction']].loc['United States']
full_country_stats[['GDP per capita', 'Life satisfaction']].loc['United States']
# 排除的索引值
remove_indices = [0, 1, 6, 8, 33, 34, 35]

# 保留的索引值 (range(36) 与 remove_indices 取差集)
keep_indices = list(set(range(36)) - set(remove_indices))

# 保留的 "GDP per capita" 和 "Life satisfaction" 数据
sample_data = full_country_stats[['GDP per capita', 'Life satisfaction']].iloc[keep_indices]

# 排除的 "GDP per capita" 和 "Life satisfaction" 数据
missing_data = full_country_stats[['GDP per capita', 'Life satisfaction']].iloc[remove_indices]
# 设置打印格式 (kind: 图表类型, x: x轴文字, y: y轴文字, figsize: 图表尺寸)
sample_data.plot(kind='scatter', x='GDP per capita', y='Life satisfaction', figsize=(5, 3))

# 图框范围 (x_min, x_max, y_min, y_max)
plt.axis([0, 60000, 0, 10])

# 标注点信息设置
position_text = {
    'Hungary': (5000, 1),
    'Korea': (18000, 1.7),
    'France': (29000, 2.4),
    'Australia': (40000, 3.0),
    'United States': (52000, 3.8),
}

# 画出标注点
for country, pos_text in position_text.items():
    # pos_data_x 为 "GDP per capita", pos_data_y 为 "Life satisfaction"
    pos_data_x, pos_data_y = sample_data.loc[country]
    # 为 "United States" 起别名
    country = 'U.S.' if country == 'United States' else country
    # 设置标注点的参数
    plt.annotate(
        country,
        xy = (pos_data_x, pos_data_y),
        xytext = pos_text,
        arrowprops = dict(facecolor='black', width=0.5, shrink=0.1, headwidth=5)
    )
    # 画出标注点 ("ro" 中的 "r表示红色", "o" 表示圆)
    plt.plot(pos_data_x, pos_data_y, 'ro')

# 保存图片
# save_fig('money_happy_scatterplot')
plt.show()
money_happy_scatterplot
# 将数据储存为 datasets/lifesat/lifesat.csv
sample_data.to_csv(os.path.join('datasets', 'lifesat', 'lifesat.csv'))
# 查询 position_text 中的国家数据
sample_data.loc[list(position_text.keys())]
sample_data.loc[list(position_text.keys())]
import numpy as np

# 设置打印格式 (kind: 图表类型, x: x轴文字, y: y轴文字, figsize: 图表尺寸)
sample_data.plot(kind='scatter', x='GDP per capita', y='Life satisfaction', figsize=(5, 3))

# 图框范围 (x_min, x_max, y_min, y_max)
plt.axis([0, 60000, 0, 10])

# 返回一个线型的范围数组 (起始值, 结束值, 数组长度), 例如: np.linspace(1, 10, 4) 将返回 [1, 4, 7, 10]
X = np.linspace(0, 60000, 1000)

# plt.plot(x, fx, color)
#   绘制直线, 参数为: 自变量, 函数关系(因变量), 线条颜色
# plt.text(x, y, text)
#   文字标注, 参数为: 文字起始点横坐标, 文字起始点纵坐标, 文字内容
# r'string'
#   原始字符串, 当字符串前面加上 "r" 后, 则该字符串为 "raw string", 其中的 "\" 不会当作转义字符, 常见于正则表达式

plt.plot(X, 2 * X / 100000, 'r')
plt.text(40000, 2.7, r'$\theta_0 = 0$', fontsize=14, color='r')
plt.text(40000, 1.8, r'$\theta_1 = 2 \times 10 ^ {-5}$', fontsize=14, color='r')

plt.plot(X, 8 - 5 * X / 100000, 'g')
plt.text(5000, 9.1, r'$\theta_0 = 8$', fontsize=14, color='g')
plt.text(5000, 8.2, r'$\theta_1 = -5 \times 10 ^ {-5}$', fontsize=14, color='g')

plt.plot(X, 4 + 5 * X / 100000, 'b')
plt.text(5000, 3.5, r'$\theta_0 = 4$', fontsize=14, color='b')
plt.text(5000, 2.6, r'$\theta_1 = 5 \times 10 ^ {-5}$', fontsize=14, color='b')

# save_fig('tweaking_model_params_plot')

plt.show()
tweaking_model_params_plot

未完待续...

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

推荐阅读更多精彩内容