scikit-learn机器学习二 (简单线性回归、K-临近算法-分类和回归、特征缩放)

简单线性回归


简单线性回归的模拟

回归问题的目标什取预测一个连续响应变量的值,这里我们将检验简单的线性回归,用于对一个响应变量和解释变量的特征之间的关系进行建模

一个简单的例子,我们对pizza的尺寸和价格进行线性回归分析

首先我们通过matplotlib来可视化对应的散点图

import numpy as np
import matplotlib.pyplot as plt
x = np.array([[6],[8],[10],[14],[18]]).reshape(-1, 1)
y = [7, 9, 13, 17.5, 18]
plt.figure()
plt.title("pizza price plotted against diameter")
plt.xlabel('diameter of pizza')
plt.ylabel('price')
plt.plot(x,y,'k.')
plt.grid(True)
plt.show()

这是matplotlib所绘制出的散点图:
在这里插入图片描述
然后我们通过sk-learn 来拟合模型
具体代码:

from sklearn.linear_model import LinearRegression//引入模块
model = LinearRegression() //创建实例
model.fit(x, y) //根据数据拟合模型
test = np.array([[12]]) //给出一个新的数据
predict = model.predict(test)[0] //使用模型预测新数据的映射
print("%.2f" % predict) //打印

输出结果

13.68

简单线性模型假设响应变量和解释变量之间存储线性关系,它使用一个被称为超平面的线性面来对这种关系进行建模。

这里的LinearRegression类是一个估计器。估计其基于观测到的数据预测一个值,sk-learn中所有的估计器都实现了fit和predict方法。前者用于学习模型的参数,后者用于学习到的参数来预测一个解释变量对应的响应变量值


用代价函数评价模型的拟合性

我们根据一些参数集合的值绘制出几条回归曲线,我们如何评估哪组参数值产生了最佳的拟合回归线呢?

我们用到代价函数,也称损失函数,它用于定义和衡量一个模型的误差。

在测试数据中预测值和观测值之间的差值叫做预测误差或者测试误差。上面这个模型的残差由训练实例点和回归超平面之间的垂直线来表示

所以我们可以通过最小化残差和来生成最佳的预测器,这种拟合方法叫做残差平方和(RSS)代价函数

K-邻近算法 分类

K-临近模型

KNN模型是一种用于回归任务和分类任务的简单模型

算法中的邻居代表的是度量空间中的训练实例。度量空间是定义了集合中所有成员之间距离的特征空间。邻居由于估计一个测试实例对应的响应变量值。超参K用来指定估计过程应该包含多少个邻居。一般需要人为指定K的值

KNN算法可以用于二元分类、多元分类以及多标签分类任务,这里我们关注二元分类任务,我们一般会将K设为奇数来防止平局现象

惰性学习和非参数模型

这里的定义很有意思,KNN是一种惰性学习模型,也就是基于实例的学习模型,会对训练数据集进行少量的处理或者完全不处理(看起来很懒惰)

和简单线性回归这样的勤奋学习模型不同,KNN在训练阶段不会估计由模型产生的参数。惰性学习有利有弊(劳逸结合)训练勤奋学习模型通常很耗费计算资源,但是在模型预测阶段代价并不昂贵。而读性学习模型几乎可以进行即刻预计,但要付出高昂的代价

KNN是一种非参数模型。参数模型通常使用固定的参数或者系数去定义能够对数据进行总结的模型,参数的数量独立于训练实例的数量

非参数模型并不是不需要参数,而是说模型的参数个数并不固定,可能随着训练实例数量的增加而增加

尤其当训练数据庞大同时你对响应变量和解释变量之间的关系所知甚少时,非参数模型将会非常有用

KNN模型分类

我们通过使用一个人的身高和体重来预测性别。由于响应变量只能从两个标签(男或女)二选一,因此这个问题称为二元分类

但是这与简单线性回归问题又不太一样,这里我们使用两个解释变量(身高和体重)来预测响应变量(性别)。但是KNN不仅限于两个特征的情况,我们可以使用任意数量的特征,但是我们需要注意一点:当特征数量多于3时将无法进行可视化

实战代码(通过身高和体重预测性别-KNN)

我们和上面采用一样的方式,先使用matplotlib绘制散点图将训练数据可视化:

import numpy as np
import matplotlib.pyplot as plt

x_train = np.array([
    [158,64],
    [170,86],
    [183,84],
    [191,80],
    [155,49],
    [163,59],
    [180,67],
    [158,54],
    [170,67],
]) # 表示身高体重
y_train = ['male', 'male', 'male', 'male', 'female', 'female', 'female', 'female', 'female']    # 表示性别
plt.figure()
plt.title('heights and weights by sex')
plt.xlabel('height in cm')
plt.ylabel('weight in kg')
for i,x in enumerate(x_train):
    plt.scatter(x[0],x[1],c='k',marker='x'if y_train[i]=='male' else 'D')    # X标记男性,菱形标记女性
plt.grid(True)
plt.show()

我们将会得到这样的图像:
在这里插入图片描述
下面我们假设预测对象为身高155,体重70
我们使用KNN预测其性别
首先我们应该定义距离衡量方法,这里我们使用欧几里得距离
即在一个欧几里得空间中两点之间的直线距离

重点:如何预测
我们给定K值为3,所以我们选择三个欧几里得距离最近的解释变量作为邻居,在邻居中女性占多数(2个)所以我们预测其为女性

下面我们使用sklearn 来实现

这里先补充一下reshape的用法
reshape用于转换为特定维数的矩阵
obj.reshape(row,column)

from sklearn.preprocessing import LabelBinarizer
from sklearn.neighbors import KNeighborsClassifier

lb = LabelBinarizer()    # 数据预处理
y_train_binarized = lb.fit_transform(y_train)    # 将字符串转换为0,1
print(y_train_binarized)
K = 3
clf = KNeighborsClassifier(n_neighbors=K)
clf.fit(x_train, y_train_binarized.reshape(-1))
predict = clf.predict(np.array([155, 70]).reshape(1, -1))[0]    
# 最后的[0]表示第一个标签的预测值
# 新版的sklearn中所有的数据都应该是二维矩阵,需要使用.reshape(1,-1)进行转换
predict_label = lb.inverse_transform(predict)    # 转换回来原来的字符串
print(predict_label)

输出结果:

[[1]
 [1]
 [1]
 [1]
 [0]
 [0]
 [0]
 [0]
 [0]]    # 转换后的y_train列表
['female']    # 预测结果为女性

下面的代码是对结果进行分析的一些函数:

x_test = np.array([[168, 65],[180, 96], [160, 52], [169, 67]])
y_test = ['male', 'male', 'female', 'female']
y_test_bin = lb.transform(y_test)
predict_test = clf.predict(x_test)    # 预测结果
predict_test_label = lb.inverse_transform(predict_test)    # 转义输出
print(predict_test) 
print(predict_test_label) 

#测试函数的引入
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
from sklearn.metrics import classification_report
from sklearn.metrics import matthews_corrcoef

# 输出正确率
print(accuracy_score(y_test_bin, predict_test))

# 返回精准率
# 准确率是为正向类测试实例被预测为正向类的比率
# 在这个例子中,正向类为男性
print(precision_score(y_test_bin, predict_test))

# 召回率是真实为正向类的测试实例被预测为正向类的比率,因为两个男性中有一个被预测为了女性,所以召回率为0.5
print(recall_score(y_test_bin, predict_test))

# F1得分是精准率和召回率的调和平均数
print(f1_score(y_test_bin, predict_test))

# 马修斯相关系数MCC是另一种对二元分类器性能衡量的选择,(-1,1):1表示完美分类器,-1表示完全错误分类器,0表示随机预测分类器
print(matthews_corrcoef(y_test_bin, predict_test))

# 一键生成精准率、召回率、F1得分的函数
print(classification_report(y_test_bin, predict_test, target_names=['male'], labels=[1]))

输出结果:

[0 1 0 0]
['female' 'male' 'female' 'female']
0.75
1.0
0.5
0.6666666666666666
0.5773502691896258
              precision    recall  f1-score   support

        male       1.00      0.50      0.67         2

   micro avg       1.00      0.50      0.67         2
   macro avg       1.00      0.50      0.67         2
weighted avg       1.00      0.50      0.67         2

K-临近算法 回归

回归任务:通过身高和性别预测体重

这里我们引入两个用于衡量回归任务性能的新指标——平均绝对误差(MAE)和均方误差(MSE)

还有r2决定系数(r2_score):
模型越好:r2→1
模型越差:r2→0

具体代码:

import numpy as np
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

x_train = np.array([
    [158, 1],
    [170, 1],
    [183, 1],
    [191, 1],
    [155, 0],
    [163, 0],
    [180, 0],
    [158, 0],
    [170, 0],
])
y_train = [64, 86, 84, 80, 49, 59, 67, 54, 67]
x_test = np.array([
    [168, 1],
    [180, 1],
    [160, 0],
    [169, 0]
])
y_test = [65, 96, 52, 67]
K = 3
clf = KNeighborsRegressor(n_neighbors=K)
clf.fit(x_train, y_train)
predict = clf.predict(x_test)
print(predict)
print(r2_score(y_test, predict))
print(mean_absolute_error(y_test, predict))
print(mean_squared_error(y_test, predict))

输出结果:

[70.66666667 79.         59.         70.66666667]
0.6290565226735438
8.333333333333336
95.8888888888889

特征缩放

最后简单的介绍一下特征缩放的概念

当特征具有相同的取值范围时,许多学习算法将会运行得更好

这里可以使用sklearn库中的StandardScaler类,它是一个用于特征缩放的转换器,它将所有实例特征值减去均值来将其居中。其次将每个实例特征值除以特征的标准差对其进行缩放。

我们称均值为0,方差为1的数据为标准化数据

具体的可以参考我后面的两篇文章哟!

scikit-learn机器学习八 (数据预处理)

scikit-learn机器学习九(特征工程)

感谢您的耐心阅读!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

国家一级假勤奋研究牲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值