这本书实在是让我眼前一亮!!! 感觉写的真的太棒了!
参考:用mermaid在typora中画思维导图
读取数据
Kaggle的话注意打开Internet On的按钮
import pandas as pd #导入Pandas,用于数据读取和处理
# 读入房价数据,示例代码中的文件地址为internet链接,读者也可以下载该文件到本机进行读取
# 如,当数据集和代码文件位于相同本地目录,路径名应为"./house.csv",或直接放"house.csv"亦可
df_housing = pd.read_csv("https://raw.githubusercontent.com/huangjia2019/house/master/house.csv")
df_housing.head() #显示加州房价数据
这是加州各地区房价的整体统计信息(不是 一套套房子的价格信息),是1990年的人口普查结果之一,共包含17 000个样本。其中包含每一个具体地区的经度(longitude)、纬度 (latitude)、房屋的平均年龄(housing_median_age)、房屋数量 (total_rooms)、家庭收入中位数(median_income)等信息,这些信息都是加州地区房价的特征。数据集最后一列“房价中位数” (median_house_value)是标签。
这个机器学习项目的目标,就是根据已有的数据样本,对其特征进行推理归纳,得到一个函数模型后,就可以用它推断加州其他地区的房价中位数。
构建特征集和标签集
X = df_housing.drop("median_house_value",axis = 1) #构建特征集X
y = df_housing.median_house_value #构建标签集y
划分数据集
from sklearn.model_selection import train_test_split #导入数据集拆分工具
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.2, random_state=0) #以80%/20%的比例进行数据集的拆分
选定模型,训练机器,拟合函数,确定参数
from sklearn.linear_model import LinearRegression #导入线性回归算法模型
model = LinearRegression() #使用线性回归算法
model.fit(X_train, y_train) #用训练集数据,训练机器,拟合函数,确定参数
利用模型进行预测
y_pred = model.predict(X_test) #预测测试集的Y值
print ('房价的真值(测试集)',y_test)
print ('预测的房价(测试集)',y_pred)
给预测打分
print("给预测评分:", model.score(X_test, y_test)) #评估预测结果
Sklearn线性回归模型的score属性给出的是R2分数, 它是一个机器学习模型的评估指标,给出的是预测值的方差与总体方 差之间的差异
可视化
import matplotlib.pyplot as plt #导入matplotlib画图库
#用散点图显示家庭收入中位数和房价中位数的分布
plt.scatter(X_test.median_income, y_test, color='brown')
#画出回归函数(从特征到预测标签)
plt.plot(X_test.median_income, y_pred, color='green', linewidth=1)
plt.xlabel('Median Income') #X轴-家庭收入中位数
plt.ylabel('Median House Value') #Y轴-房价中位数
plt.show() #显示房价分布和机器习得的函数图形
术语 | 定义 | 数学描述 | 示例 |
---|---|---|---|
数据集 | 数据的集合 | { ( X 1 , y 1 ) , ⋯ . ( X n , y n ) } \{(X_1,y_1),\cdots.(X_n,y_n)\} {(X1,y1),⋯.(Xn,yn)} | 1000个北京市房屋的面积、楼层、位置、朝向,以及部分房价信息的数据集 |
样本 | 数据集中的一条具体记录 | { ( X 1 , y 1 ) } \{(X_1,y_1)\} {(X1,y1)} | 一个房屋的数据记录 |
特征 | 用于描述数据的输入变量 | { x 1 , x 2 , ⋯ . x n } \{x_1,x_2,\cdots.x_n\} {x1,x2,⋯.xn}也是一个向量 | 面积( x 1 {x_1} x1)、楼层( x 2 {x_2} x2)、位置( x 3 {x_3} x3)、朝向( x 4 {x_4} x4) |
标签 | 要预测的真实事物或结果,也称为目标 | y | 房价 |
有标签样本 | 有特征、标签,用于训练模型 | (X,y) | 800个北京市房屋的面积、楼层、位置、朝向,以及房价信息 |
无标签样本 | 有特征,无标签 | (X, ?) | 200个北京市房屋的面积、楼层、位置、朝向,但是无房价信息 |
模型 | 将样本的特征映射到预测标签 | f(X),其实也就是函数 | 通过面积、楼层、位置、朝向这些信息来确定房价的函数 |
模型中的参数 | 模型中的参数确定了机器学习的具体模型 | f(X)这个函数的参数 | 如f(X)=3X+2中的3和2 |
模型的映射结果 | 通过模型映射出无标签样本的标签 | y’ | 200个被预测出来的房价 |
机器学习 | 通过学习样本数据,发现规律,得到模型的参数,从而得到能预测目标的模型 | 确定f(X)和其参数的过程 | 确定房价预测函数和具体参数的过程 |
8个机器学习常用库
Pandas和Num Py提供数据结构,支持数学运算
Matplotlib和Seaborn用于数据可视化
4个库提供算法
Scikit-learn是机器学习框架
简称Sklearn
from sklearn.linear_model import Linear Regression #导入
线性回归算法模型
model = Linear Regression() #使用线性回归算法
Tesnsor Flow、Keras和PyTorch则是深度学习框架
李宏毅老师曾用将大象装进冰箱来比喻机器学习。
机器学习项目的实际过程要更复杂一些,大致分为以下5个环节。
这5个环节,每一步的处理是否得当,都直接影响机器学习项目的 成败
用MNIST数据集为例
要知道机器学习项目到底要解决什么问题
例
可视化(visualization)
数据向量化(data vectorization)
处理坏数据和缺失值
特征缩放(feature scaling)
数据预处理原则
特征工程和特征提取仍然是在机器对数据集学习之前进行的操作,广义上也算数据预处理。
特征工程是使用数据的领域知识来创建使机器学习算法起作用的特征的过程。特征工程是机器学习的重要环节,然而这个环节实施困难又开销昂贵,相当费时费力。
特征提取(feature extraction)则是通过子特征的选择来减少冗余特征,使初始测量数据更简洁,同时保留最有用的信息。
为什么要对数据的特征进行处理?因为机器学习之所以能够学到 好的算法,关键看特征的质量。那就需要思考下面的问题。
如何选择最有用的特征给机器进行学习?(进行特征提 取。)
如何把现有的特征进行转换、强化、组合,创建出来新的、 更好的特征?(进行特征工程。)
import numpy as np # 导入NumPy数学工具箱
import pandas as pd # 导入Pandas数据处理工具箱
from keras.datasets import mnist #从Keras中导入mnist数据集
#读入训练集和测试集
(X_train_image, y_train_lable), (X_test_image, y_test_lable) = mnist.load_data()
数据向量化的工作MNIST数据集已经为我们做好了,可以直接显 示这些张量里面的内容:
print ("特征集张量形状:", X_train_image.shape) #用shape方法显示张量的形状
print ("第一个数据样本:\n", X_train_image[0]) #注意Python的索引是从0开始的
shape方法显示的是X_train_image张量的形状。灰度图像数据集是 3D张量,第一个维度是样本维(也就是一张一张的图片,共60 000 张),后面两个是特征维(也就是图片的28px×28px的矩阵)。可以发现灰度 信息主要集中在矩阵的中部,边缘部分都是0填充,是图片的背景。数字矩阵的内容差不多如下图所示。
再看一下标签的格式:
print ("第一个数据样本的标签:", y_train_lable[0])
第一个数据样本的标签: 5
上面的数据集在输入机器学习模型之前还要做一些数据格式转换 的工作:
# from keras.utils.np_utils import to_categorical # 导入keras.utils工具箱的类别转换工具
from tensorflow.python.keras.utils.np_utils import to_categorical # 导入keras.utils工具箱的类别转换工具
X_train = X_train_image.reshape(60000,28,28,1) # 给标签增加一个维度
X_test = X_test_image.reshape(10000,28,28,1) # 给标签增加一个维度
y_train = to_categorical(y_train_lable, 10) # 特征转换为one-hot编码
y_test = to_categorical(y_test_lable, 10) # 特征转换为one-hot编码
print ("数据集张量形状:", X_train.shape) # 特征集张量的形状
print ("第一个数据标签:",y_train[0]) # 显示标签集的第一个数据
书上那个 from keras.utils.np_utils import to_categorical # 导入keras.utils工具箱的类别转换工具
改成上面那个tensorflow.python.keras.utils就
from keras import models # 导入Keras模型, 和各种神经网络的层
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D
model = models.Sequential() # 用序贯方式建立模型
model.add(Conv2D(32, (3, 3), activation='relu', # 添加Conv2D层
input_shape=(28,28,1))) # 指定输入数据样本张量的类型
model.add(MaxPooling2D(pool_size=(2, 2))) # 添加MaxPooling2D层
model.add(Conv2D(64, (3, 3), activation='relu')) # 添加Conv2D层
model.add(MaxPooling2D(pool_size=(2, 2))) # 添加MaxPooling2D层
model.add(Dropout(0.25)) # 添加Dropout层
model.add(Flatten()) # 展平
model.add(Dense(128, activation='relu')) # 添加全连接层
model.add(Dropout(0.5)) # 添加Dropout层
model.add(Dense(10, activation='softmax')) # Softmax分类激活,输出10维分类码
# 编译模型
model.compile(optimizer='rmsprop', # 指定优化器
loss='categorical_crossentropy', # 指定损失函数
metrics=['accuracy']) # 指定验证过程中的评估指标
第3个环节先是选择机器学习模型的算法类型,然后才开始训练机器确定参数。 各种Python机器学习框架中有很多类型的算法,主要包括以下几种
线性模型(线性回归、逻辑回归)
非线性模型(支持向量机、k最邻近分类)
基于树和集成的模型(决策树、随机森林、梯度提升树等)
神经网络(人工神经网络、卷积神经网络、长短期记忆网络等)
那么究竟用哪个呢? 答案是—这与要解决的问题有关。没有最好的算法,也没有最差 的算法。
随机森林也许处理回归类型问题很给力,而神经网络则适合处理特征量巨大的数据,有些算法还能够通过集成学习的方法组织在一起使用。只有通过实践和经验的积累,深入地了解各个算法,才能 慢慢地形成“机器学习直觉”。遇见的多了,一看到问题,就知道大 概何种算法比较适合。
那么我们为MNIST数据集手写数字识别的问题选择什么算法作为 机器学习模型呢?试试卷积神经网络
from keras import models # 导入Keras模型, 和各种神经网络的层
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D
model = models.Sequential() # 用序贯方式建立模型
model.add(Conv2D(32, (3, 3), activation='relu', # 添加Conv2D层
input_shape=(28,28,1))) # 指定输入数据样本张量的类型
model.add(MaxPooling2D(pool_size=(2, 2))) # 添加MaxPooling2D层
model.add(Conv2D(64, (3, 3), activation='relu')) # 添加Conv2D层
model.add(MaxPooling2D(pool_size=(2, 2))) # 添加MaxPooling2D层
model.add(Dropout(0.25)) # 添加Dropout层
model.add(Flatten()) # 展平
model.add(Dense(128, activation='relu')) # 添加全连接层
model.add(Dropout(0.5)) # 添加Dropout层
model.add(Dense(10, activation='softmax')) # Softmax分类激活,输出10维分类码
# 编译模型
model.compile(optimizer='rmsprop', # 指定优化器
loss='categorical_crossentropy', # 指定损失函数
metrics=['accuracy']) # 指定验证过程中的评估指标
from tqdm.keras import TqdmCallback
model.fit(X_train, y_train, # 指定训练特征集和训练标签集
validation_split = 0.3, # 部分训练集数据拆分成验证集
epochs=5, # 训练轮次为5轮
batch_size=128,callbacks=[TqdmCallback(verbose=2)]
) # 以128为批量进行训练
在上面的训练过程中,fit方法还自动地把训练集预留出30%的数据 作为验证集(马上就会讲到什么是验证集),来验证模型准确率。 输出结果如下:
以上显示的5轮训练中,准确率逐步提高。
accuracy:代表训练集上的预测准确率,最后一轮达到0.9726
val_accuracy:代表验证集上的预测准确率,最后一轮达到0.9798
为了进行模型的评估,一般会把数据划分成3个集合:训练数据 集、验证数据集和测试数据集,简称训练集(trainsing set)、验证集 (validation set)和测试集(test set)。在训练集上训练模型,在验证集上评估模型。感觉已经找到最佳的模型内部参数和超参数之后,就在测试集上进行最终测试,以确定模型。
机器学习模型训练时,会自动调节模型内部参数。
这个过程中经常出现 过拟合(overfit) 的现象。
可以把过拟合理 解为模型对当前数据集的针对性过强了,虽然对训练集拟合效果很好,但是换一批新数据就不灵了。这叫作模型的泛化能力弱。
解决了在训练集上的过拟合问题之后,在继续优化模型的过程中,又需要反复地调整模型外部的超参数,这个过程是在训练集和验证集中共同完成的。这个调试、验证过程会导致模型在验证集上也可能过拟合,因为调试超参数本身也是一种训练。这个现象叫作信息泄露(information leak)。也就是说,即使我们选择了对验证集效果最好的超参数,这个好结果也不一定真的能泛化到最终的测试集。
即使得到的模型在验证集上的性能已经非常好,我们关心的还是模型在全新数据上的性能。因此,我们需要使用一个完全不同的、前所未见的数据集来对模型进行最终的评估和校正,它就是测试集。在最终验证之前,我们的模型一定不能读取任何与测试集有关的任何信息,一次也不行。
下面就在MNIST测试集上进行模型效率的验证,如下段代码所示。这个测试集的任何数据信息都没有在模型训练的过程中暴露过。
score = model.evaluate(X_test, y_test) # 在测试集上进行模型评估
print('测试集预测准确率:', score[1]) # 打印测试集上的预测准确率
优化(optimization)和泛化(generalization),这是机器学习的两 个目标。它们之间的关系很微妙,是一种此消彼长的状态。
模型能否泛化,也许比模型在当前数据集上的性能优化更重要。
经过训练之后100张猫图片都能被认出来了,但是也没什么了不起,因为这也许是通过死记硬背实现的(书上这里说的好好),再给几张新的猫图片,就不认识 了。这就有可能是出现了“过拟合”的问题—机器学习到的模型太过于关注训练数据本身。
对于目前的MNIST数据集,卷积神经网络模型是没有出现过拟合的问题的,因为在训练集、验证集和测试集中,评估后的结果都差不多, 预测准确率均为98%以上,所以模型泛化功能良好。
怎么看预测结果
pred = model.predict(X_test[0].reshape(1, 28, 28, 1)) # 预测测试集第一个数据
print(pred[0],"转换一下格式得到:",pred.argmax()) # 把one-hot码转换为数字
import matplotlib.pyplot as plt # 导入绘图工具包
plt.imshow(X_test[0].reshape(28, 28),cmap='Greys') # 输出这个图片
前两行代码,是对测试集第一个数据(Python索引是从0开始的) 进行预测,并输出预测结果。argmax方法就是输出数组里面最大元素的索引,也就是把one-hot编码转换为实际数值。 输出结果如下
果然是正确答案7,与预测结果的one-hot编码相匹配,证明预测对了!
机器学习的内涵:
机器学习的关键内涵在于从大量的数据中发现一个“模型”,并通过它来模拟现实世界事物间的关系, 从而实现预测或判断的功能。
从这个定义出发,机器学习可以分为监督学习、无监督学习、 半监督学习,以及深度学习、强化学习等类型。这些学习类型之间的界限是比较模糊的,彼此之间有交集,也可以相互组合。比如,深度 学习和强化学习技术同时运用,可以形成深度强化学习模型。
基本的机器学习术语
机器学习项目实战流程中的5个环节
使 用 Linear Regression线性回归算法对波士顿房价数据集进行建模
代码
import numpy as np # 导入NumPy数学工具箱
import pandas as pd # 导入Pandas数据处理工具箱
from keras.datasets import boston_housing #从Keras中导入Boston Housing数据集
#读入训练集和测试集
(X_train, y_train), (X_test, y_test) = boston_housing.load_data()
print ("数据集张量形状:", X_train.shape) #shape方法显示张量的形状
print ("第一个数据样本:\n", X_train[0]) #注意Python的索引是从0开始的
print ("第一个数据样本的标签:", y_train[0])
from sklearn.linear_model import LinearRegression #导入线性回归算法模型
model = LinearRegression() #使用线性回归算法
model.fit(X_train, y_train) #用训练集数据,训练机器,拟合函数,确定参数
y_pred = model.predict(X_test) #预测测试集的Y值
print ('房价的真值(测试集)',y_test)
print ('预测的房价(测试集)',y_pred)
print("给预测评分:", model.score(X_test, y_test)) #评估预测结果