本文构建第一个机器学习模型,并介绍一些核心概念和术语。
假设有一名植物学家对莺尾花品种很感兴趣,他收集了每一朵莺尾花一些测量数据:花瓣的长度和宽度以及花萼的长度和宽度。所测量结果单位为厘米。
他还有一些燕尾花的测量数据,这些花之前已经被植物学家鉴定为
setosa,versicolor和virginica三个品种之一。对于这些测量数据他可以确定梅朵燕尾花的品种,假设这位植物学家在野外遇到了这三种燕尾花。
我们的目标是构建一个机器学习模型,可以从从这些已知品种燕尾花测量数据中学习,从而能够预测新燕尾花的品种。
因为我们有已知的燕尾花品种数据,所以这是一个监督学习问题。我么要在多个选项中预测其中一个,这是一个分类(classification)问题的事例。可能的输出叫做类别(class)。这是一个三分类问题。
单个数据点(一朵燕尾花)的预期输出是这朵花的品种。对于一个数据点来说,他的品种叫标签(label)。
初识数据
本例中用到的莺尾花(iris)数据集,这是机器学习和统计学中经典数据集,他包含在scikit-learn的datasets模块中。可以调用load_iris函数加载。
from sklearn.datasets import load_iris
iris_dataset=load_iris()
load_iris返回iris的对象是一个bunch对象,与字典非常相似,里面包含键和值:
print ("key of the iris_dataset:\n{}".format(iris_dataset.keys()))
DESCR键对应的值是数据集的简要说明。我这里给出了署名的开头。
print(iris_dataset['DESCR'][:139]+"\n...")
#输出结果
.. _iris_dataset:
Iris plants dataset
--------------------
**Data Set Characteristics:**
:Number of Instances: 150 (50 in each of th
...
target_names键对应的值是一个字符串数组,里面包含了我们要预测的花的品种。
print ("target names:[]".format(iris_dataset['target_names']))
target names:[‘setosa’ ‘versicolor’ ‘virginica’]*
fetature_names键对应的值是一个字符串列表,对每一个特征进行了说明。
print ("feature name:\n{}".format(iris_dataset['feature_names']))
feature name:
[‘sepal length (cm)’, ‘sepal width (cm)’, ‘petal length (cm)’, ‘petal width (cm)’]
数据包含在target和data字段中。data里面的花萼长度,花萼宽度,花瓣长度,花瓣宽度的测量数据,格式为numpy数组:
print("type of data:\n{}".format(type(iris_dataset['data'])))
type of data:
data数组每一行代表一朵花,列代表每朵花的四个测量数据:
print ("shape of data:{}".format(iris_dataset['data'].shape))
shape of data:(150, 4)
可以看出,数据中包含150朵的测量数据。机器学习中的个体叫做样本(sample),其属性叫做特征(feature)。data数组的形状(shape)是样本乘以特征数。这是scikit-learn中的约定。
下面给出前五个样本的特征值:
print("first five rows of data:\n{}".format(iris_dataset['data'][:5]))
first five rows of data:
[[ 5.1 3.5 1.4 0.2]
[ 4.9 3. 1.4 0.2]
[ 4.7 3.2 1.3 0.2]
[ 4.6 3.1 1.5 0.2]
[ 5. 3.6 1.4 0.2]]
从前五个数据看出前五个花瓣的宽度都是0.2cm。
target数组是包含测量过的每一朵花的品种,也是一个numpy数组。
print ("type of target:{}".format(type(iris_dataset['target'])))
type of target:
target是一维数组,每朵花对应其中一个数据:
print ("shape of target:{}".format(iris_dataset['target'].shape))
shape of target:(150,)
品种被转化为0到2的整数:
print ("target:\n{}".format(iris_dataset['target']))
target:
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2]
0代表setosa,1代表versicolor,2代表virginica
模型的泛化能力:选料好的模型应用于新的数据集上表现得效果,效果越好证明泛化能力越强,反之亦然。
对数据调用函数train_test_split:
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test=train_test_split(iris_dataset['data'],iris_dataset['target'],random_state=0)
!!!值得注意的是train_test_split函数可以将数据打乱,如果我们不打乱将最后的25%数据作为测试数据的花那么所有的数据点的标签都将是2,因为数据点是按标签排序的。
print ("X_train shape :{}".format(X_train.shape))
print ("y_train shape :{}".format(y_train.shape))
X_train shape :(112, 4)
y_train shape :(112,)
print ("X_test shape :{}".format(X_test.shape))
print ("y_test shape :{}".format(y_test.shape))
X_test shape :(38, 4)
y_test shape :(38,)
构建机器学习模型之前一般先看看数据,看看如果不用机器学习能不能轻松搞定,或需要的信息有没有包含在面。观察数据还是发现异常值得好办法。
一种可视化方法是画散点图(scatter plot),但对于3个或更多特征可以画散点图矩阵(pair plot)。
为了画散点矩阵图我们将numpy数组转化为pandas的dataFrame,pandas有个绘制散点图的函数叫做scatter_matrix。矩阵对角线是每个特征的直方图
import pandas as pd
#利用X_train中的数据创建DataFrame
#利用iris_dataset.feature_names中的字符串对数据进行标记
iris_dataframe=pd.DataFrame(X_train,columns=iris_dataset.feature_names)
#利用DataFrame创建散点图矩阵,按y_train着色
ris_dataframe=pd.DataFrame(X_train,columns=iris_dataset.feature_names)
grr=pd.plotting.scatter_matrix(iris_dataframe,c=y_train,figsize=(15,15),marker="o",hist_kwds={"bins":20},s=60,alpha=.8)
散点矩阵图:
scikit-learn中有很多分类算法,这里我么用K近邻分类器。
核心思想是对一个新的数据点预测,算法会在训练集中寻找这个数据点最近的数据点,然后把这个数据点的标签赋值给这个新的数据点。
废话不多说了,还是上代码吧。
from sklearn.neighbors import KNeighborsClassifier
knn=KneighborsClassifier(n_neighbor=1)
knn.fit(X_train,y_train)
《》《》《》《》《》《》《》《》《》《》《》待续》》》》》》》》》》》》》》