待更
来源于《Python机器学习基础教程》一书,机器学习之旅从鸢尾花开始~
注意:python中机器学习数据集结构:
feature | target |
---|---|
X1,…,Xn | y |
data | target |
X | y |
scikit-learn 中的数据通常用大写的X 表示,而标签用小写的y 表示。这是来源于f(x)=y ,其中x 是函数的输入,y 是输出。大写的X是因为数据是一个二维数组(矩阵),小写的y 是因为目标是一个一维数组(向量),这也是数学中的约定。
导入包并加载数据
import numpy as np
import pandas as pd
import seaborn as sns # 美化绘图
import sklearn
from sklearn.datasets import load_iris # 导入数据集
iris_dataset = load_iris() # 加载后的数据是Bunch对象,类似于字典
print("Keys of iris_dataset:\n{}".format(iris_dataset.keys()))
# 其中DESCR是数据集的说明
Keys of iris_dataset:
dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names', 'filename'])
print(iris_dataset['DESCR']) # print带格式,直接输出没有格式
著名的鸢尾花数据集, 请注意,它与R中的相同,但与UCI中的不同
机器学习存储库,其中有两个错误的数据点。
print(iris_dataset['target_names']) # 类别名
print(iris_dataset['feature_names']) # 特征名
print(type(iris_dataset['data'])) # 数据结构
print(iris_dataset['data'].shape) # 维度
print(iris_dataset['data'][:5]) # 数据前五行
print(type(iris_dataset['target'])) # target's type
print(iris_dataset['target'].shape) # target's shape
iris_dataset['target'] # 0,1,2
iris_dataset['target_names']
# array(['setosa', 'versicolor', 'virginica'], dtype='
scikit-learn 中的train_test_split 函数可以随机打乱数据集并进行拆分。默认将75% 的行数据及对应标签作为训练集,剩下25% 的数据及其标签作为测试集。使用25% 的数据作为测试集是很好的经验法则。
from sklearn.model_selection import train_test_split
X, y = iris_dataset['data'], iris_dataset['target']
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=0)
print(X_train.shape) # (112, 4)
# Split arrays or matrices into random train and test subsets
?train_test_split
X_train, X_test, y_train, y_test = train_test_split(data_X,data_y,…) : 返回4个array
- test_size : if float,between 0.0 and 1.0,测试集应占的比例,默认0.25;if int,表示测试集中的样本数
- random_state : If int, random_state is the seed used by the random number generator;随机数种子
- shuffle :(default=True):在拆分前是否随机打乱数据顺序
注:详情与示例见docstring
散点图,将一个特征作为x 轴,另一个特征作为y 轴,将每一个数据点绘制为图上的一个点,一次只能绘制两个特征,对多于3 个特征的数据集作图,绘制散点图矩阵。
散点图矩阵无法同时显示所有特征之间的关系,只能两两查看,所以这种可视化方法可能无法展示数据的某些有趣内容。
建议使用seaborn绘制
# 先转换为dataframe,然后使用pandas.scatter_matrix(),对角线是每个特征的直方图或密度图
df = pd.DataFrame(X_train,columns=iris_dataset['feature_names'])
# 创建散点图矩阵,按y_train着色(一列标签)。因为X_train和y_train一一对应
grr = pd.plotting.scatter_matrix(df,c=y_train,figsize=(10,10),marker='.',hist_kwds={'bins':20},s=60,alpha=0.8)
pandas自带绘图函数pd.plotting.scatter_matrix(frame)
可选参数:(详见docstring)
- diagonal:必须且只能在{‘hist’, ‘kde’}中选择1个,’hist’表示直方图,’kde’表示核密度估计(Kernel Density Estimation),该参数是scatter_matrix函数的关键参数。
- hist_kwds:与hist相关的字典参数
- c:颜色
对于散点图矩阵,seaborn包画图更美观。
sns绘制散点图矩阵所需的数据结构是X与y在一起的一个df。
使用详情参见docstring。
y_train_se = pd.Series(y_train) # se可以自动变换类型,array不可以
y_train_se[y_train_se == 0] = 'setosa' # 方便图例生成
y_train_se[y_train_se == 1] = 'versicolor'
y_train_se[y_train_se == 2] = 'virginica'
df['class'] = y_train_se # sns绘制散点图矩阵所需的数据结构是X与y在一起的一个df
sns.pairplot(df,plot_kws={'alpha':0.8},hue='class') # hue为df中一列的列名,为不同的点标记颜色,该列的值为图例,按类别标签着色
参考:
https://blog.csdn.net/zyb228/article/details/101940096/
https://www.jianshu.com/p/6e18d21a4cad
- k近邻分类器:构建此模型只需要保存训练集即可。要对一个新的数据点做出预测,算法会在训练集中寻找与这个新数据点距离最近的数据点,然后将找到的数据点的标签赋值给这个新数据点。
- k的含义是,我们可以考虑训练集中与新数据点最近的任意k个邻居,用这些邻居中数量最多的类别做出预测。
- scikit-learn 中所有的机器学习模型都在各自的类中实现。k 近邻分类算法是在neighbors 模块的KNeighborsClassifier 类中实现的。需要将这个类实例化为一个对象,然后才能使用这个模型。这时我们需要设置模型的参数。
- KNeighborsClassifier 最重要的参数就是邻居的数目
docstring的示例:
?KNeighborsClassifier
Examples
--------
>>> X = [[0], [1], [2], [3]]
>>> y = [0, 0, 1, 1]
>>> from sklearn.neighbors import KNeighborsClassifier
>>> neigh = KNeighborsClassifier(n_neighbors=3)
>>> neigh.fit(X, y) # doctest: +ELLIPSIS
KNeighborsClassifier(...)
>>> print(neigh.predict([[1.1]]))
[0]
>>> print(neigh.predict_proba([[0.9]]))
[[0.66666667 0.33333333]]
应用:
from sklearn.neighbors import KNeighborsClassifier # knn也可用于回归,是KNeighborsRegression
knn = KNeighborsClassifier(n_neighbors=1) # 设置具体参数来实例化
knn 对象对算法进行了封装,既包括用训练数据构建模型的算法,也包括对新数据点进行预测的算法。它还包括算法从训练数据中提取的信息。
对KNeighborsClassifier 来说,里面只保存了训练集。
想要基于训练集来构建模型,需要调用knn 对象的fit 方法,输入参数为X_train 和y_train,二者都是NumPy 数组,前者包含训练数据,后者包含相应的训练标签:
knn.fit(X_train,y_train) # fit 方法返回的是knn 对象本身并做原处修改,因此得到分类器的字符串表示。从中可以看出构建模型时用到的参数。
# 模型都有很多参数,但多用于速度优化或非常特殊的用途。
可以通过计算精度(accuracy)来衡量模型的优劣,精度就是品种预测正确的花所占的比例:
# 得到测试集的预测值
y_pred = knn.predict(X_test)
y_pred # array([2, 1, 0, 2, 0, 2, 0, 1, 1, 1, 2, 1, 1, 1, 1, 0, 1, 1, 0, 0, 2, 1,0, 0, 2, 0, 0, 1, 1, 0, 2, 1, 0, 2, 2, 1, 0, 2])
# 与测试集的真实值比较得到精度
np.mean(y_pred == y_test) # 0,1之间算1的比例就是所有的平均值,等价于
knn.score(X_test,y_test) # 0.9736842105263158
?knn.score
Returns the mean accuracy on the given test data and labels.
X_new = np.array([[5,2.9,1,0.2]]) # 一条新数据
print(X_new.shape) # (1, 4),二维数组的一行,因为scikit-learn的输入数据必须是二维数组。
prediction = knn.predict(X_new) # 预测
prediction # array([0]) ,类别是0
iris_dataset['target_names'][prediction] # array(['setosa'], dtype='
from sklearn.datasets import load_breast_cancer
import sklearn
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt
cancer = load_breast_cancer()
cancer.keys()
print(cancer.DESCR)
# 拆分训练集与测试集
X_train,X_test,y_train,y_test = train_test_split(cancer.data,cancer.target,stratify=cancer.target,random_state=66)
strtigy : array-like, 数据以分层方式拆分,并将其用作类标签。按不同类别所占比例拆分?并转换为0,1标签?
## 记录训练集精度和测试集精度
n_max = 10
n_range = range(1,n_max+1) # 邻居范围
train_acc = np.zeros(n_max)
test_acc = np.zeros(n_max)
for i,n in enumerate(n_range):
knn = KNeighborsClassifier(n_neighbors=n)
knn.fit(X_train,y_train)
train_acc[i] = knn.score(X_train,y_train)
test_acc[i] = knn.score(X_test,y_test)
## 画图
plt.plot(n_range,train_acc,label='train acc')
plt.plot(n_range,test_acc,label='test_acc',linestyle='--')
plt.xlabel('n neighbors')
plt.ylabel('Accuracy')
plt.legend()
可以看出,更少的邻居对应更复杂的模型,训练集精度高,测试集精度低,最近邻是过拟合。
泛化最佳性能在n=6时,测试集精度最高。
最差的性能约为88% 的精度,这个结果仍然可以接受。
from sklearn.neighbors import KNeighborsRegressor # kNN回归器
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
# 模型实例化,并将邻居个数设为3
reg = KNeighborsRegressor(n_neighbors=3)
# 利用训练数据和训练目标值来拟合模型
reg.fit(X_train, y_train)
# 预测结果
reg.predict(X_test)
# 评估模型
reg.score(X_test, y_test)