机器学习重温笔记(二):常用经典算法篇,解决基础数据预测问题

机器学习(常用算法篇)

前言:由于机器学习的基础算法对于数据分析非常重要,有小伙伴私信我能不能梳理之前文科转码时快速学习常用算法基础的方法,今天下班后花了很多时间重新梳理了一下机器学习基础之(常用算法篇),能够解决大多数机器学习上的统计预测计算任务!希望对各位小伙伴有帮助!

文章目录

一、K-近邻算法

pip3 install scikit-learn==0.19.1

1. 距离公式

1.欧式距离
	通过距离平方值进行计算
2.曼哈顿距离(Manhattan Distance):
    通过举例的绝对值进行计算
3.切比雪夫距离 (Chebyshev Distance):
    维度的最大值进行计算
4.闵可夫斯基距离(Minkowski Distance):
    当p=1时,就是曼哈顿距离;
    当p=2时,就是欧氏距离;
    当p→∞时,就是切比雪夫距离。
小结:前面四个距离公式都是把单位相同看待了,所以计算过程不是很科学

5.标准化欧氏距离 (Standardized EuclideanDistance):
    在计算过程中添加了标准差,对量刚数据进行处理
6.余弦距离(Cosine Distance)
    通过cos思想完成
7.汉明距离(Hamming Distance)【了解】:
    一个字符串到另一个字符串需要变换几个字母,进行统计
8.杰卡德距离(Jaccard Distance)【了解】:
    通过交并集进行统计
9.马氏距离(Mahalanobis Distance)【了解】
    通过样本分布进行计算

2. k值的选择

  • 1-K值过小

容易受到异常点的影响

  • 2-k值过大:

受到样本均衡的问题

  • 3-注意:

K值的减小就意味着整体模型变得复杂,容易发生过拟合;

K值过大,与输入实例较远训练实例使预测发生错误,意味着整体的模型变得简单。

近似误差:近似误差过小可能会出现过拟合的现象,对训练集能有很好的预测,但对未知的测试样本将会出现较大偏差的预测。

估计误差:可以理解为对测试集的测试误差,关注测试集,估计误差小说明对未知数据的预测能力好,模型本身最接近最佳模型。

3. kd树

kd树:为了避免每次都重新计算一遍距离,算法会把距离信息保存在一棵树里,这样在计算之前从树里查询距离信息,尽量避免重新计算。其基本原理是,如果A和B距离很远,B和C距离很近,那么A和C的距离也很远。就可以在合适的时候跳过距离远的点。

  • 1.树的建立;

  • 2.最近邻域搜索(Nearest-Neighbor Lookup)

kd树(K-dimension tree)是**一种对k维空间中的实例点进行存储以便对其进行快速检索的树形数据结构。**kd树是一种二叉树,表示对k维空间的一个划分,构造kd树相当于不断地用垂直于坐标轴的超平面将K维空间切分,构成一系列的K维超矩形区域。kd树的每个结点对应于一个k维超矩形区域。利用kd树可以省去对大部分数据点的搜索,从而减少搜索的计算量。

4. 鸢尾花种类预测

(1) 数据集介绍

sklearn.datasets.
小数据:
sklearn.datasets.load_*
注意:
该数据从本地获取
大数据集:
sklearn.datasets.fetch_*
注意:
该数据从网上下载
subset–表示获取到的数据集类型:‘train’或者’test’,‘all’,可选,选择要加载的数据集。

(2) 数据集返回值介绍

返回值类型是bunch–是一个字典类型
返回值的属性:
data:特征数据数组
target:标签(目标)数组
DESCR:数据描述
feature_names:特征名,
target_names:标签(目标值)名

from sklearn.datasets import load_iris
# 获取鸢尾花数据集
iris = load_iris()
print("鸢尾花数据集的返回值:\n", iris)
# 返回值是一个继承自字典的Bench
print("鸢尾花的特征值:\n", iris["data"])
print("鸢尾花的目标值:\n", iris.target)
print("鸢尾花特征的名字:\n", iris.feature_names)
print("鸢尾花目标值的名字:\n", iris.target_names)
print("鸢尾花的描述:\n", iris.DESCR)
(3) 数据可视化

seaborn.lmplot():

​ x,y 表示横纵坐标的列名,

​ data是关联到的数据集,

​ hue表示按照哪个进行分类显示,

​ fit_reg是否进行线性拟合。

%matplotlib inline  
# 内嵌绘图
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

# 把数据转换成dataframe的格式
iris_d = pd.DataFrame(	iris['data'], 
						columns = ['Sepal_Length', 'Sepal_Width', 'Petal_Length', 'Petal_Width'])
iris_d['Species'] = iris.target

def plot_iris(iris, col1, col2):
    sns.lmplot(x = col1, y = col2, data = iris, hue = "Species", fit_reg = False)
    plt.xlabel(col1)
    plt.ylabel(col2)
    plt.title('鸢尾花种类分布图')
    plt.show()
plot_iris(iris_d, 'Petal_Width', 'Sepal_Length')
(4) 数据集划分

sklearn.model_selection.train_test_split()

  • x 数据集的特征值
  • y 数据集的标签值
  • test_size 测试集的大小,一般为float,默认是0.25
  • random_state 随机数种子,不同的种子会造成不同的随机采样结果。相同的种子采样结果相同。
  • return 测试集特征训练集特征值值,训练标签,测试标签(默认随机取)
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 1、获取鸢尾花数据集
iris = load_iris()

# 对鸢尾花数据集进行分割
# 训练集的特征值x_train 测试集的特征值x_test 训练集的目标值y_train 测试集的目标值y_test
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22)
print("x_train:\n", x_train.shape)

# 随机数种子
x_train1, x_test1, y_train1, y_test1 = train_test_split(iris.data, iris.target, random_state=6)
x_train2, x_test2, y_train2, y_test2 = train_test_split(iris.data, iris.target, random_state=6)

print("如果随机数种子不一致:\n", x_train == x_train1)
print("如果随机数种子一致:\n", x_train1 == x_train2)

5. 特征工程特征预处理

定义:将特征数据转换成更加适合算法模型的特征数据过程

(1) 为什么我们要进行归一化/标准化?
  • 特征的单位或者大小相差较大,或者某特征的方差相比其他的特征要大出几个数量级容易影响(支配)目标结果,使得一些算法无法学习到其它的特征
(2) 归一化
  • 通过对原始数据进行变换把数据映射到(默认为[0,1])之间,鲁棒性较差,只适合传统精确小数据场景。
  • sklearn.preprocessing.MinMaxScaler (feature_range=(0,1)… )
    • MinMaxScalar.fit_transform(X)
      • X:numpy array格式的数据[n_samples,n_features]
    • 返回值:转换后的形状相同的array
1、实例化MinMaxScalar

2、通过fit_transform转换

import pandas as pd
from sklearn.preprocessing import MinMaxScaler

def minmax_demo():
    """
    归一化演示
    :return: None
    """
    data = pd.read_csv("dating.txt")
    print(data)
    # 1、实例化一个转换器类
    transfer = MinMaxScaler(feature_range=(2, 3))
    
    # 2、调用fit_transform
    data = transfer.fit_transform(data[['milage','Liters','Consumtime']])
    print("最小值最大值归一化处理的结果:\n", data)

    return None
     milage     Liters  Consumtime  target
0     40920   8.326976    0.953952       3
1     14488   7.153469    1.673904       2
2     26052   1.441871    0.805124       1
3     75136  13.147394    0.428964       1
..      ...        ...         ...     ...
998   48111   9.134528    0.728045       3
999   43757   7.882601    1.332446       3

[1000 rows x 4 columns]
最小值最大值归一化处理的结果:
 [[ 2.44832535  2.39805139  2.56233353]
 [ 2.15873259  2.34195467  2.98724416]
 [ 2.28542943  2.06892523  2.47449629]
 ..., 
 [ 2.29115949  2.50910294  2.51079493]
 [ 2.52711097  2.43665451  2.4290048 ]
 [ 2.47940793  2.3768091   2.78571804]]
(3) 标准化
  • 通过对原始数据进行变换把数据变换到均值为0,标准差为1范围内,适合现代嘈杂大数据场景
1、实例化StandardScaler

2、通过fit_transform转换

import pandas as pd
from sklearn.preprocessing import StandardScaler

def stand_demo():
    """
    标准化演示
    :return: None
    """
    data = pd.read_csv("dating.txt")
    print(data)
    # 1、实例化一个转换器类
    transfer = StandardScaler()
    # 2、调用fit_transform
    data = transfer.fit_transform(data[['milage','Liters','Consumtime']])
    print("标准化的结果:\n", data)
    print("每一列特征的平均值:\n", transfer.mean_)
    print("每一列特征的方差:\n", transfer.var_)

    return None
     milage     Liters  Consumtime  target
0     40920   8.326976    0.953952       3
1     14488   7.153469    1.673904       2
2     26052   1.441871    0.805124       1
..      ...        ...         ...     ...
997   26575  10.650102    0.866627       3
998   48111   9.134528    0.728045       3
999   43757   7.882601    1.332446       3

[1000 rows x 4 columns]
标准化的结果:
 [[ 0.33193158  0.41660188  0.24523407]
 [-0.87247784  0.13992897  1.69385734]
 [-0.34554872 -1.20667094 -0.05422437]
 ..., 
 [-0.32171752  0.96431572  0.06952649]
 [ 0.65959911  0.60699509 -0.20931587]
 [ 0.46120328  0.31183342  1.00680598]]
每一列特征的平均值:
 [  3.36354210e+04   6.55996083e+00   8.32072997e-01]
每一列特征的方差:
 [  4.81628039e+08   1.79902874e+01   2.46999554e-01]

6. 鸢尾草案例

导入模块
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier

# 1.获取数据集
iris = load_iris()

# 2.数据基本处理
# x_train,x_test,y_train,y_test为训练集特征值、测试集特征值、训练集目标值、测试集目标值
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=22)

# 3、特征工程:标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)

# 4、机器学习(模型训练)
estimator = KNeighborsClassifier(n_neighbors=9)
estimator.fit(x_train, y_train)

# 5、模型评估
# 方法1:比对真实值和预测值
y_predict = estimator.predict(x_test)
print("预测结果为:\n", y_predict)
print("比对真实值和预测值:\n", y_predict == y_test)

# 方法2:直接计算准确率
score = estimator.score(x_test, y_test)
print("准确率为:\n", score)

7. K-近邻算法总结

优点:
1.简单有效
2.重新训练代价低
3.适合类域交叉样本
4.适合大样本自动分类
缺点:
1.惰性学习
2.类别评分不是规格化
3.输出可解释性不强
4.对不均衡的样本不擅长
样本不均衡:收集到的数据每个类别占比严重失衡
5.计算量较大

8. 交叉验证和网格搜索

(1) 交叉验证
  • 1.定义:
    将拿到的训练数据,分为训练和验证集
    *折交叉验证
  • 2.分割方式:
    训练集:训练集+验证集
    测试集:测试集
  • 3.为什么需要交叉验证
    为了让被评估的模型更加准确可信
    注意:交叉验证不能提高模型的准确率
(2) 网格搜索
  • 超参数:
    sklearn中,需要手动指定的参数,叫做超参数
    网格搜索就是把这些超参数的值,通过字典的形式传递进去,然后进行选择最优值
(3) api:
  • sklearn.model_selection.GridSearchCV(estimator, param_grid=None,cv=None)
    estimator – 选择了哪个训练模型
    param_grid – 需要传递的超参数
    cv – 几折交叉验证
  • 结果分析:
    • bestscore__:在交叉验证中验证的最好结果
    • bestestimator:最好的参数模型
    • cvresults:每次交叉验证后的验证集准确率结果和训练集准确率结果
  • 鸢尾草案例:
# 1、获取数据集
iris = load_iris()
# 2、数据基本处理 -- 划分数据集
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22)
# 3、特征工程:标准化
# 实例化一个转换器类
transfer = StandardScaler()
# 调用fit_transform
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4、KNN预估器流程
#  4.1 实例化预估器类
estimator = KNeighborsClassifier()

# 4.2 模型选择与调优——网格搜索和交叉验证
# 准备要调的超参数
param_dict = {"n_neighbors": [1, 3, 5]}
estimator = GridSearchCV(estimator, param_grid=param_dict, cv=3)
# 4.3 fit数据进行训练
estimator.fit(x_train, y_train)

# 5、评估模型效果
# 方法a:比对预测结果和真实值
y_predict = estimator.predict(x_test)
print("比对预测结果和真实值:\n", y_predict == y_test)

# 方法b:直接计算准确率
score = estimator.score(x_test, y_test)
print("直接计算准确率:\n", score)

print("在交叉验证中验证的最好结果:\n", estimator.best_score_)
print("最好的参数模型:\n", estimator.best_estimator_)
print("每次交叉验证后的准确率结果:\n", estimator.cv_results_)
比对预测结果和真实值:
 [ True  True  True  True  True  True  True False  True  True  True  True
  True  True  True  True  True  True False  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True]

    直接计算准确率:
 0.947368421053

    在交叉验证中验证的最好结果:
 0.973214285714

最好的参数模型:
 KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=1, n_neighbors=5, p=2,
           weights='uniform')

    每次交叉验证后的准确率结果:
 {'mean_fit_time': array([ 0.00114751,  0.00027037,  0.00024462]), 'std_fit_time': array([  1.13901511e-03,   1.25300249e-05,   1.11011951e-05]), 'mean_score_time': array([ 0.00085751,  0.00048693,  0.00045625]), 'std_score_time': array([  3.52785082e-04,   2.87650037e-05,   5.29673344e-06]), 'param_n_neighbors': masked_array(data = [1 3 5],
             mask = [False False False],
       fill_value = ?)
, 'params': [{'n_neighbors': 1}, {'n_neighbors': 3}, {'n_neighbors': 5}], 'split0_test_score': array([ 0.97368421,  0.97368421,  0.97368421]), 'split1_test_score': array([ 0.97297297,  0.97297297,  0.97297297]), 'split2_test_score': array([ 0.94594595,  0.89189189,  0.97297297]), 'mean_test_score': array([ 0.96428571,  0.94642857,  0.97321429]), 'std_test_score': array([ 0.01288472,  0.03830641,  0.00033675]), 'rank_test_score': array([2, 3, 1], dtype=int32), 'split0_train_score': array([ 1.        ,  0.95945946,  0.97297297]), 'split1_train_score': array([ 1.        ,  0.96      ,  0.97333333]), 'split2_train_score': array([ 1.  ,  0.96,  0.96]), 'mean_train_score': array([ 1.        ,  0.95981982,  0.96876877]), 'std_train_score': array([ 0.        ,  0.00025481,  0.0062022 ])}

9. facebook案例

import pandas as pd
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier

# 1、获取数据集
facebook = pd.read_csv("./data/FBlocation/train.csv")

# 2.基本数据处理
# 2.1 缩小数据范围
facebook_data = facebook.query("x>2.0 & x<2.5 & y>2.0 & y<2.5")

# 2.2 选择时间特征
time = pd.to_datetime(facebook_data["time"], unit="s")
time = pd.DatetimeIndex(time)
facebook_data["day"] = time.day
facebook_data["hour"] = time.hour
facebook_data["weekday"] = time.weekday

# 2.3 去掉签到较少的地方
place_count = facebook_data.groupby("place_id").count()
place_count = place_count[place_count["row_id"]>3]
facebook_data = facebook_data[facebook_data["place_id"].isin(place_count.index)]

# 2.4 确定特征值和目标值
x = facebook_data[["x", "y", "accuracy", "day", "hour", "weekday"]]
y = facebook_data["place_id"]

# 2.5 分割数据集
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=22)

# 3.特征工程--特征预处理(标准化)
# 3.1 实例化一个转换器
transfer = StandardScaler()

# 3.2 调用fit_transform
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)

# 4.机器学习--knn+cv
# 4.1 实例化一个估计器
estimator = KNeighborsClassifier()

# 4.2 调用gridsearchCV
param_grid = {"n_neighbors": [1, 3, 5, 7, 9]}
estimator = GridSearchCV(estimator, param_grid=param_grid, cv=5)
# 4.3 模型训练
estimator.fit(x_train, y_train)

# 5.模型评估
# 5.1 基本评估方式
score = estimator.score(x_test, y_test)
print("最后预测的准确率为:\n", score)

y_predict = estimator.predict(x_test)
print("最后的预测值为:\n", y_predict)
print("预测值和真实值的对比情况:\n", y_predict == y_test)

# 5.2 使用交叉验证后的评估方式
print("在交叉验证中验证的最好结果:\n", estimator.best_score_)
print("最好的参数模型:\n", estimator.best_estimator_)
print("最好的参数:\n", estimator.best_params_)
print("每次交叉验证后的验证集准确率结果和训练集准确率结果:\n",estimator.cv_results_)

二、线性回归

应用场景:

  • 房价预测
  • 销售额度预测
  • 贷款额度预测

1. 线性回归的损失和优化

(1) 损失

最小二乘法

(2) 优化

正规方程

梯度下降法

(3) 正规方程

一蹴而就,利用矩阵的逆,转置进行求解,适合样本和特征较少的情况

def linear_model1():
    """
    线性回归:正规方程
    :return:None
    """
    # 1.获取数据
    data = load_boston()

    # 2.数据集划分
    x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)

    # 3.特征工程-标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.fit_transform(x_test)

    # 4.机器学习-线性回归(特征方程)
    estimator = LinearRegression()
    estimator.fit(x_train, y_train)

    # 5.模型评估
    # 5.1 获取系数等值
    y_predict = estimator.predict(x_test)
    print("预测值为:\n", y_predict)
    print("模型中的系数为:\n", estimator.coef_)
    print("模型中的偏置为:\n", estimator.intercept_)

    # 5.2 评价
    # 均方误差
    error = mean_squared_error(y_test, y_predict)
    print("误差为:\n", error)
(4) 梯度下降法 – 循序渐进
  • 举例:
    山 – 可微分的函数
    山底 – 函数的最小值

  • 梯度的概念
    单变量 – 切线
    多变量 – 向量

  • 梯度下降法中关注的两个参数
    α – 就是步长
    步长太小 – 下山太慢
    步长太大 – 容易跳过极小值点(*****)
    为什么梯度要加一个负号
    梯度方向是上升最快方向,负号就是下降最快方向

(5) 梯度下降法和正规方程对比:

​ 梯度下降 正规方程
​ 需要选择学习率 不需要
​ 需要迭代求解 一次运算得出
​ 特征数量较大可以使用 需要计算方程,时间复杂度高O(n3)

(6) 选择:
  • 小规模数据:
    LinearRegression(不能解决拟合问题)
    岭回归
  • 大规模数据:
    SGDRegressor

2.梯度下降法

(1) 全梯度下降算法(FG)

在进行计算的时候,计算所有样本的误差平均值,作为目标函数

(2) 随机梯度下降算法(SG)

每次只选取一个样本进行考核

(3) 小批量梯度下降算法(mini-batch)

选取一部分样本进行考核

(4) 随机平均梯度下降算法(SAG)

会给每一个样本都维持一个平均值,后期计算的时候,参考这个平均值

(5) api介绍
sklearn.linear_model.SGDRegressor(loss="squared_loss", 
                                  fit_intercept=True, 
                                  learning_rate ='invscaling', 
                                  eta0=0.01)
参数:
                1.loss -- 损失 (最小二乘)
                2.learning_rate -- 学习率
                    一般时都是进行动态的更新,也可以指定成为一个常数,但是不推荐。
def linear_model2():
    """
    线性回归:梯度下降法
    :return:None
    """
    # 1.获取数据
    data = load_boston()

    # 2.数据集划分
    x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)

    # 3.特征工程-标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.fit_transform(x_test)

    # 4.机器学习-线性回归(特征方程)
    estimator = SGDRegressor(max_iter=1000)
    # estimator = SGDRegressor(max_iter=1000,learning_rate="constant",eta0=0.1)
    estimator.fit(x_train, y_train)

    # 5.模型评估
    # 5.1 获取系数等值
    y_predict = estimator.predict(x_test)
    print("预测值为:\n", y_predict)
    print("模型中的系数为:\n", estimator.coef_)
    print("模型中的偏置为:\n", estimator.intercept_)

    # 5.2 评价
    # 均方误差
    error = mean_squared_error(y_test, y_predict)
    print("误差为:\n", error)

3. 欠拟合和过拟合

(1) 欠拟合
  • 在训练集上表现不好,在测试集上表现不好
  • 解决方法:( 继续学习)
    • 1-添加其他特征项
    • 2-添加多项式特征
(2) 过拟合
  • 在训练集上表现好,在测试集上表现不好
  • 解决方法:
    • 1.重新清洗数据集
    • 2.增大数据的训练量
    • 3.正则化
    • 4.减少特征维度
(3) 正则化
  • 通过限制高次项的系数进行防止过拟合

  • L1正则化:

    • 理解:直接把高次项前面的系数变为0
    • Lasso回归
  • L2正则化:

    • 理解:把高次项前面的系数变成特别小的值
    • 岭回归
(4) 正则化线性模型
  • 1.Ridge Regression 岭回归
    就是把系数添加平方项
    然后限制系数值的大小
    α值越小,系数值越大,α越大,系数值越小
  • 2.Lasso 回归
    对系数值进行绝对值处理
    由于绝对值在顶点处不可导,所以进行计算的过程中产生很多0,最后得到结果为:稀疏矩阵
  • 3.Elastic Net 弹性网络
    是前两个内容的综合
    设置了一个r,如果r=0–岭回归;r=1–Lasso回归
  • 4.Early stopping
    通过限制错误率的阈值,进行停止
(5) 线性回归的改进-岭回归
sklearn.linear_model.Ridge(alpha=1.0, 
                           fit_intercept=True,
                           solver="auto", 
                           normalize=False)
        具有l2正则化的线性回归
        alpha -- 正则化
            正则化力度越大,权重系数会越小
            正则化力度越小,权重系数会越大
        normalize
            默认封装了,对数据进行标准化处理
def linear_model3():
    """
    线性回归:岭回归
    :return:
    """
    # 1.获取数据
    data = load_boston()

    # 2.数据集划分
    x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)

    # 3.特征工程-标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.fit_transform(x_test)

    # 4.机器学习-线性回归(岭回归)
    estimator = Ridge(alpha=1)
    # estimator = RidgeCV(alphas=(0.1, 1, 10))
    estimator.fit(x_train, y_train)

    # 5.模型评估
    # 5.1 获取系数等值
    y_predict = estimator.predict(x_test)
    print("预测值为:\n", y_predict)
    print("模型中的系数为:\n", estimator.coef_)
    print("模型中的偏置为:\n", estimator.intercept_)

    # 5.2 评价
    # 均方误差
    error = mean_squared_error(y_test, y_predict)
    print("误差为:\n", error)
(5) 模型的保存与加载
import pandas as pd
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LinearRegression,SGDRegressor,Ridge
from sklearn.metrics import  mean_squared_error
import joblib
api:
    sklearn.externals import joblib
        保存:joblib.dump(estimator, 'test.pkl')
        加载:estimator = joblib.load('test.pkl')
    注意:
    1.保存文件,后缀名是**.pkl
    2.加载模型是需要通过一个变量进行承接
def load_dump_demo():
    """
    线性回归:岭回归
    :return:
    """
    # 1.获取数据
    data = load_boston()

    # 2.数据集划分,注意要有随机数种子
    x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)

    # 3.特征工程-标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.fit_transform(x_test)

    # 4.机器学习-线性回归(岭回归)
    # # 4.1 模型训练
    # estimator = Ridge(alpha=1)
    # estimator.fit(x_train, y_train)
    #
    # # 4.2 模型保存
    # joblib.dump(estimator, "./data/test.pkl")

    # 4.3 模型加载
    estimator = joblib.load("./data/test.pkl")

    # 5.模型评估
    # 5.1 获取系数等值
    y_predict = estimator.predict(x_test)
    print("预测值为:\n", y_predict)
    print("模型中的系数为:\n", estimator.coef_)
    print("模型中的偏置为:\n", estimator.intercept_)

    # 5.2 评价
    # 均方误差
    error = mean_squared_error(y_test, y_predict)
    print("误差为:\n", error)

三、逻辑回归

应用场景:解决二分类问题,逻辑回归的输入是线性回归的输出。

  • 广告点击率
  • 是否为垃圾邮件
  • 是否患病
  • 金融诈骗
  • 虚假账号

1. 原理

  • 1-激活函数:sigmoid(),将整体的值映射到 [0,1],再设置一个阈值,进行分类判断。

  • 2-损失:对数似然损失,借助log思想,以真实值为0或1进行划分

  • 3-优化:提升原本属于类别1的概率,降低原本等于类别0的概率

2. API介绍

​ sklearn.linear_model.LogisticRegression()
​ 注意:回归,分类api有时候是可以混合使用的

3. 案例:癌症分类预测-良/恶性乳腺癌肿瘤预测【**】

1.获取数据
2.基本数据处理
2.1 缺失值处理
2.2 确定特征值,目标值
2.3 分割数据
3.特征工程(标准化)
4.机器学习(逻辑回归)
5.模型评估
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report

import ssl
ssl._create_default_https_context = ssl._create_unverified_context

# 1.获取数据
names = ['Sample code number', 'Clump Thickness', 'Uniformity of Cell Size', 'Uniformity of Cell Shape',
                   'Marginal Adhesion', 'Single Epithelial Cell Size', 'Bare Nuclei', 'Bland Chromatin',
                   'Normal Nucleoli', 'Mitoses', 'Class']

data = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data",
                  names=names)
data.head()
# 2.基本数据处理
# 2.1 缺失值处理
data = data.replace(to_replace="?", value=np.NaN)
data = data.dropna()

# 2.2 确定特征值,目标值
x = data.iloc[:, 1:10]
x.head()
y = data["Class"]
y.head()

# 2.3 分割数据
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=22)

# 3.特征工程(标准化)
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)

# 4.机器学习(逻辑回归)
estimator = LogisticRegression()
estimator.fit(x_train, y_train)

# 5.模型评估
y_predict = estimator.predict(x_test)
y_predict
estimator.score(x_test, y_test)

# 0.5~1之间,越接近于1约好

y_test = np.where(y_test > 2.5, 1, 0)

print("AUC指标:", roc_auc_score(y_test,y_predict))

4. 分类评估方法

(1) 混淆矩阵

​ 真正例(TP):我猜正,答案为正
​ 伪反例(FN):我猜反,答案为正
​ 伪正例(FP):我猜正,答案为反
​ 真反例(TN):我猜反,答案为反

(2) 精确率(Precision)与召回率(Recall)
  • 准确率:(对不对)
    (TP+TN)/(TP+TN+FN+FP)

  • 精确率 – 查的准不准,我猜正
    TP/(TP+FP)

  • 召回率 – 查的全不全,答案是正
    TP/(TP+FN)

  • F1-score – 反映模型的稳健性

    2 * Precision * Recall / ( Precision + Recall )

(3) API介绍

​ sklearn.metrics.classification_report(y_true,y_pred,labels=(几行,几列),target_names=None )

ret = classification_report(y_test, y_predict, labels=(2,4), target_names=("良性", "恶性"))
print(ret)

   precision    recall  f1-score   support

          良性       0.98      0.98      0.98       111
          恶性       0.97      0.97      0.97        60

    accuracy                           0.98       171
   macro avg       0.97      0.97      0.97       171
weighted avg       0.98      0.98      0.98       171
(4) roc曲线和auc指标
  • TPR = TP / (TP + FN)
    • 所有真实类别为1的样本中,预测类别为1的比例
  • FPR = FP / (FP + TN)
    • 所有真实类别为0的样本中,预测类别为1的比例
  • roc曲线
    • ROC曲线的横轴就是FPRate,纵轴就是TPRate,
    • 当二者相等时:对于不论真实类别是1还是0的样本,分类器预测为1的概率是相等的,此时AUC为0.5
    • auc
      越接近1,效果越好
      越接近0,效果越差
      越接近0.5,效果就是胡说
    • 注意:
      这个指标主要用于评价不平衡的二分类问题
  • api介绍:
    sklearn.metrics.roc_auc_score(y_true, y_score)
    y_true – 要把正例转换为1,反例转换为0
(5) ROC 曲线绘制
  • 1.构建模型,把模型的概率值从大到小进行排序
  • 2.从概率最大的点开始取值,一直进行tpr和fpr的计算,然后构建整体模型,得到结果
  • 3.其实就是在求解积分(面积)

四、决策树算法

1. 原理

(1) 信息增益

信息增益 = entroy(前) - entroy (后)

注意:信息增益优先选择属性类别较多的进行划分,信息增益越大,优先选择该属性进行计算

(2) 信息增益率

维持了一个分离信息度量,通过这个度量当分母进行限制

(3) 基尼增益
  • 1-基尼值

    从数据集D中随机两个样本,其类别标记不一样的概率,Dini(D) 值越小,数据集D纯度越高

  • 2-基尼指数

    选择使划分后基尼系数最小的属性作为最优划分属性

  • 3-基尼增益

    选择基尼增益最大的点进行优化划分

  • 4-基尼增益构造过程

    • 1.开始将所有记录看作一个节点
    • 2.遍历每个变量的每一种分割方式,找到最好的分割点
    • 3.分割成两个节点N1和N2
    • 4.对N1和N2分别继续执行2-3步,直到每个节点足够“纯”为止。
  • 5-决策树的变量两种,分别划分方式:

    • 1.数字型
      通过对数据取两个数字之间的中间值,进行划分
      2.名称型
      通过对属性的类别进行划分
  • 6-如何评估分割点的好坏?

    主要看分割的是否纯

(4) 三种算法对比:【****】
  • 1-ID3 算法

    • 采用信息增益作为评价标准

    • 只能对描述属性为离散型属性的数据集构造决策树

    • 缺点是倾向于选择取值较多的属性

  • 2-C4.5算法

    • 用信息增益率来选择属性

    • 可以处理连续数值型属性

    • 采用了一种后剪枝方法

    • 对于缺失值的处理

    • 缺点是:C4.5只适合于能够驻留于内存的数据集

  • 3-CART算法

    • C4.5不一定是二叉树,但CART一定是二叉树
    • 是信息增益的简化版本,同时特征选择采用了近似的基尼系数来简化计算。

2. CART 剪枝

(1) 原因
  • 1-噪声、样本冲突,即错误的样本数据
  • 2-特征即属性不能完全作为分类标准
  • 3-巧合的规律性,数据量不够大。
(2) 方法
  • 1-预剪枝

    • 在构建树的过程中,同时剪枝
      eg:

      ​ 限制节点最小样本数
      ​ 指定数据高度
      ​ 指定熵值的最小值

  • 2-后剪枝

    • 把一棵树,构建完成之后,再进行从下往上的剪枝

3.特征工程-特征提取【***】

(1) 特征提取

将任意数据(如文本或图像)转换为可用于机器学习的数字特征

(2) 特征提取分类

字典特征提取(特征离散化)
文本特征提取
图像特征提取(深度学习将介绍)

(3) api介绍

sklearn.feature_extraction

(4) 字典特征提取

字典特征提取就是对类别型数据进行转换
api:
sklearn.feature_extraction.DictVectorizer(sparse=True,…)
sparse矩阵
1.节省内容
2.提高读取效率
属性:
DictVectorizer.get_feature_names() 返回类别名称,新版本用 get_feature_names_out()
注意:
对于特征当中存在类别信息的我们都会做one-hot编码处理

from sklearn.feature_extraction import DictVectorizer

def dict_demo():
    """
    对字典类型的数据进行特征抽取
    :return: None
    """
    data = [{'city': '北京','temperature':100}, {'city': '上海','temperature':60}, {'city': '深圳','temperature':30}]
    # 1、实例化一个转换器类
    transfer = DictVectorizer(sparse=False)
    # 2、调用fit_transform
    data = transfer.fit_transform(data)
    print("返回的结果:\n", data)
    # 打印特征名字
    
    # 报错:AttributeError: 'DictVectorizer' object has no attribute 'get_feature_names'
    print("特征名字:\n", transfer.get_feature_names_out())

    return None

dict_demo()
返回的结果:
 [[  0.   1.   0. 100.]
 [  1.   0.   0.  60.]
 [  0.   0.   1.  30.]]
特征名字:
 ['city=上海' 'city=北京' 'city=深圳' 'temperature']
(5) 文本特征提取(英文)

api:
sklearn.feature_extraction.text.CountVectorizer(stop_words=[])
stop_words – 停用词
注意:没有sparse这个参数
单个字母,标点符号不做统计

from sklearn.feature_extraction.text import CountVectorizer

def text_count_demo():
    """
    对文本进行特征抽取,countvetorizer
    :return: None
    """
    data = ["life is short,i like like python", "life is too long,i dislike python"]
    # 1、实例化一个转换器类
    # transfer = CountVectorizer(sparse=False) # 注意,没有sparse这个参数
    transfer = CountVectorizer()
    # 2、调用fit_transform
    data = transfer.fit_transform(data)
    print("文本特征抽取的结果:\n", data.toarray())
    print("返回特征名字:\n", transfer.get_feature_names_out())

    return None

text_count_demo()
文本特征抽取的结果:
 [[0 1 1 2 0 1 1 0]
 [1 1 1 0 1 1 0 1]]
返回特征名字:
 ['dislike' 'is' 'life' 'like' 'long' 'python' 'short' 'too']
(6) 文本特征提取(中文)

注意:
1.在中文文本特征提取之前,需要对句子(文章)进行分词(jieba)
2.里面依旧可以使用停用词,进行词语的限制

from sklearn.feature_extraction.text import CountVectorizer
import jieba

def cut_word(text):
    """
    对中文进行分词
    "我爱北京天安门"————>"我 爱 北京 天安门"
    :param text:
    :return: text
    """
    # 用结巴对中文字符串进行分词
    text = " ".join(list(jieba.cut(text)))

    return text

def text_chinese_count_demo2():
    """
    对中文进行特征抽取
    :return: None
    """
    data = ["一种还是一种今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。",
            "我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。",
            "如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。"]
    # 将原始数据转换成分好词的形式
    text_list = []
    for sent in data:
        text_list.append(cut_word(sent))
    print(text_list)

    # 1、实例化一个转换器类
    # transfer = CountVectorizer(sparse=False)
    transfer = CountVectorizer()
    # 2、调用fit_transform
    data = transfer.fit_transform(text_list)
    print("文本特征抽取的结果:\n", data.toarray())
    print("返回特征名字:\n", transfer.get_feature_names_out())

    return None

text_chinese_count_demo2()
['一种 还是 一种 今天 很 残酷 , 明天 更 残酷 , 后天 很 美好 , 但 绝对 大部分 是 死 在 明天 晚上 , 所以 每个 人 不要 放弃 今天 。', '我们 看到 的 从 很 远 星系 来 的 光是在 几百万年 之前 发出 的 , 这样 当 我们 看到 宇宙 时 , 我们 是 在 看 它 的 过去 。', '如果 只用 一种 方式 了解 某样 事物 , 你 就 不会 真正 了解 它 。 了解 事物 真正 含义 的 秘密 取决于 如何 将 其 与 我们 所 了解 的 事物 相 联系 。']
文本特征抽取的结果:
 [[2 0 1 0 0 0 2 0 0 0 0 0 1 0 1 0 0 0 0 1 1 0 2 0 1 0 2 1 0 0 0 1 1 0 0 1 0]
  [0 0 0 1 0 0 0 1 1 1 0 0 0 0 0 0 0 1 3 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 1 0 1]
  [1 1 0 0 4 3 0 0 0 0 1 1 0 1 0 1 1 0 1 0 0 1 0 0 0 1 0 0 0 2 1 0 0 1 0 0 0]]
返回特征名字:
 ['一种' '不会' '不要' '之前' '了解' '事物' '今天' '光是在' '几百万年' '发出' '取决于' '只用' '后天' '含义'
 '大部分' '如何' '如果' '宇宙' '我们' '所以' '放弃' '方式' '明天' '星系' '晚上' '某样' '残酷' '每个'
 '看到' '真正' '秘密' '绝对' '美好' '联系' '过去' '还是' '这样']
(7) TF-IDF

1.主要思想:
某个词或短语在一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类
2.tfidf
tf – 词频
idf – 逆向文档频率
3.api
sklearn.feature_extraction.text.TfidfVectorizer
注意:
分类机器学习算法进行文章分类中前期数据处理方式

from sklearn.feature_extraction.text import TfidfVectorizer
import jieba

def cut_word(text):
    """
    对中文进行分词
    "我爱北京天安门"————>"我 爱 北京 天安门"
    :param text:
    :return: text
    """
    # 用结巴对中文字符串进行分词
    text = " ".join(list(jieba.cut(text)))

    return text

def text_chinese_tfidf_demo():
    """
    对中文进行特征抽取
    :return: None
    """
    data = ["一种还是一种今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。",
            "我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。",
            "如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。"]
    # 将原始数据转换成分好词的形式
    text_list = []
    for sent in data:
        text_list.append(cut_word(sent))
    print(text_list)

    # 1、实例化一个转换器类
    # transfer = CountVectorizer(sparse=False)
    transfer = TfidfVectorizer(stop_words=['一种', '不会', '不要'])
    # 2、调用fit_transform
    data = transfer.fit_transform(text_list)
    print("文本特征抽取的结果:\n", data.toarray())
    print("返回特征名字:\n", transfer.get_feature_names_out())

    return None
['一种 还是 一种 今天 很 残酷 , 明天 更 残酷 , 后天 很 美好 , 但 绝对 大部分 是 死 在 明天 晚上 , 所以 每个 人 不要 放弃 今天 。', '我们 看到 的 从 很 远 星系 来 的 光是在 几百万年 之前 发出 的 , 这样 当 我们 看到 宇宙 时 , 我们 是 在 看 它 的 过去 。', '如果 只用 一种 方式 了解 某样 事物 , 你 就 不会 真正 了解 它 。 了解 事物 真正 含义 的 秘密 取决于 如何 将 其 与 我们 所 了解 的 事物 相 联系 。']
文本特征抽取的结果:
 [[ 0.          0.          0.          0.43643578  0.          0.          0.
   0.          0.          0.21821789  0.          0.21821789  0.          0.
   0.          0.          0.21821789  0.21821789  0.          0.43643578
   0.          0.21821789  0.          0.43643578  0.21821789  0.          0.
   0.          0.21821789  0.21821789  0.          0.          0.21821789
   0.        ]
 [ 0.2410822   0.          0.          0.          0.2410822   0.2410822
   0.2410822   0.          0.          0.          0.          0.          0.
   0.          0.2410822   0.55004769  0.          0.          0.          0.
   0.2410822   0.          0.          0.          0.          0.48216441
   0.          0.          0.          0.          0.          0.2410822
   0.          0.2410822 ]
 [ 0.          0.644003    0.48300225  0.          0.          0.          0.
   0.16100075  0.16100075  0.          0.16100075  0.          0.16100075
   0.16100075  0.          0.12244522  0.          0.          0.16100075
   0.          0.          0.          0.16100075  0.          0.          0.
   0.3220015   0.16100075  0.          0.          0.16100075  0.          0.
   0.        ]]
返回特征名字:
 ['之前', '了解', '事物', '今天', '光是在', '几百万年', '发出', '取决于', '只用', '后天', '含义', '大部分', '如何', '如果', '宇宙', '我们', '所以', '放弃', '方式', '明天', '星系', '晚上', '某样', '残酷', '每个', '看到', '真正', '秘密', '绝对', '美好', '联系', '过去', '还是', '这样']
(8) api介绍

sklearn.tree.DecisionTreeClassifier(criterion=’gini’, max_depth=None,random_state=None)
参数:
criterion
特征选择标准:gini(基尼不纯度),entropy(信息熵)

​ min_samples_split
​ 内部节点再划分所需最小样本数
​ min_samples_leaf
​ 叶子节点最少样本数
​ max_depth
​ 决策树最大深度

4. 案例:泰坦尼克号乘客生存预测

import pandas as pd
import numpy as np
from sklearn.feature_extraction import DictVectorizer
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, export_graphviz

# 1、获取数据,数据网址过期
titan = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")

# 2、 数据基本处理
# 2.1 确定特征值,目标值
x = titan[["pclass", "age", "sex"]]
y = titan["survived"]

# 2.2 缺失值处理
x['age'].fillna(x['age'].mean(), inplace=True)

# 2.3 数据集划分
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=22)

# 3. 特征工程(字典特征抽取)

# 4. 机器学习
transfer = DictVectorizer(sparse=False)

x_train = transfer.fit_transform(x_train.to_dict(orient="records"))
x_test = transfer.fit_transform(x_test.to_dict(orient="records"))

# 4.机器学习(决策树),这是信息熵的标准。
estimator = DecisionTreeClassifier(criterion="entropy", max_depth=5)
estimator.fit(x_train, y_train)

# 5.模型评估
estimator.score(x_test, y_test)
estimator.predict(x_test)

5. 决策树可视化

api:sklearn.tree.export_graphviz(),能够导出DOT格式

Webgraphviz网址

export_graphviz(estimator, out_file="./data/tree.dot", feature_names=['age', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', '女性', '男性'])

优点:
简单的理解和解释,树木可视化。
缺点:
决策树学习者可以创建不能很好地推广数据的过于复杂的树,容易发生过拟合。
改进:
减枝cart算法
随机森林(集成学习的一种)

五、集成学习

1. 集成学习算法简介

(1) 什么是集成学习

​ 超级个体和弱者联盟对比,后者更优

(2) 复习:机器学习两个核心任务

​ 1.解决欠拟合问题
​ 弱弱组合变强
​ boosting
​ 2.解决过拟合问题
​ 互相遏制变壮
​ Bagging

2. Bagging【**】

(1) bagging集成过程

1.采样
从所有样本里面,采样一部分
2.学习
训练弱学习器
3.集成
使用平权投票

(2) 随机森林介绍

1.随机森林定义
随机森林 = Bagging + 决策树
2.流程:
1.随机选取m条数据
2.随机选取k个特征
3.训练决策树
4.重复1-3
5.对上面的若干决策树进行平权投票
3.注意:
1.随机选取样本,且是有放回的抽取
2.选取特征的时候吗,选择m<<M
M是所有的特征数
4.api
sklearn.ensemble.RandomForestClassifier()

import pandas as pd
import numpy as np
from sklearn.feature_extraction import DictVectorizer
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.ensemble import RandomForestClassifier

# 1、获取数据,数据网址过期
titan = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")

# 2、 数据基本处理
# 2.1 确定特征值,目标值
x = titan[["pclass", "age", "sex"]]
y = titan["survived"]

# 2.2 缺失值处理
x['age'].fillna(x['age'].mean(), inplace=True)

# 2.3 数据集划分
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=22)

# 3. 特征工程(字典特征抽取)

# 4. 机器学习
transfer = DictVectorizer(sparse=False)

x_train = transfer.fit_transform(x_train.to_dict(orient="records"))
x_test = transfer.fit_transform(x_test.to_dict(orient="records"))

# 4.机器学习(决策树),这是信息熵的标准。
estimator = RandomForestClassifier()

# 定义超参数的选择列表
param = {"n_estimators": [120,200,300,500,800,1200], "max_depth": [5, 8, 15, 25, 30]}

# 使用GridSearchCV进行网格搜索
# 超参数调优
gc = GridSearchCV(estimator, param_grid=param, cv=5)
gc.fit(x_train, y_train)

# 5.模型评估
print("随机森林预测的准确率为:", gc.score(x_test, y_test))
(3) bagging的优点

​ Bagging + 决策树/线性回归/逻辑回归/深度学习… = bagging集成学习方法
​ 1.均可在原有算法上提高约2%左右的泛化正确率
​ 2.简单, 方便, 通用

3. Boosting【**】

(1) boosting集成原理

随着学习的积累从弱到强

(2) 实现过程

1.初始化训练数据权重,初始权重是相等的
2.通过这个学习器,计算错误率
3.计算这个学习期的投票权重
4.对每个样本进行重新赋权
5.重复前面1-4
6.对构建后的最后的学习器进加权投票

(3) bagging集成与boosting集成的区别:

数据方面:
bagging:重新采样
boosting:对数据进行权重调整
投票方面:
bagging:平权
boosting:加权
学习顺序方面:
bagging:并行
boosting:串行
主要作用:
bagging:过拟合
boosting:欠拟合

(4) GBDT

梯度提升决策树(GBDT Gradient Boosting Decision Tree)
GBDT = 梯度下降 + Boosting + 决策树

(5) XGBoost

XGBoost= 二阶泰勒展开+boosting+决策树+正则化

六、聚类算法

应用:

  • 用户画像,广告推荐,Data Segmentation,搜索引擎的流量推荐,恶意流量识别
  • 基于位置信息的商业推送,新闻聚类,筛选排序
  • 图像分割,降维,识别;离群点检测;信用卡异常消费;发掘相同功能的基因片段

1. 简介

(1) 聚类算法分类

​ 粗聚类
​ 细聚类

(2) 定义

​ 一种典型的无监督学习算法,
​ 主要用于将相似的样本自动归到一个类别中
​ 计算样本和样本之间的相似性,一般使用欧式距离

2. 聚类算法api初步使用

(1) API

sklearn.cluster.KMeans(n_clusters=8)
参数:
n_clusters:开始的聚类中心数量

import matplotlib.pyplot as plt
from sklearn.datasets._samples_generator import make_blobs
from sklearn.cluster import KMeans
from sklearn.metrics import calinski_harabasz_score

# 创建数据集
# X为样本特征,Y为样本簇类别, 共1000个样本,每个样本4个特征,共4个簇,
# 簇中心在[-1,-1], [0,0],[1,1], [2,2], 簇方差分别为[0.4, 0.2, 0.2, 0.2]
X, y = make_blobs(n_samples=1000, n_features=2, centers=[[-1, -1], [0, 0], [1, 1], [2, 2]],
                  cluster_std=[0.4, 0.2, 0.2, 0.2],
                  random_state=9)

# 数据集可视化
plt.scatter(X[:, 0], X[:, 1], marker='o')
plt.show()

y_pred = KMeans(n_clusters=4, random_state=9).fit_predict(X)
# 分别尝试n_cluses=2\3\4,然后查看聚类效果
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

# 用Calinski-Harabasz Index评估的聚类分数
print(calinski_harabasz_score(X, y_pred))

3. 聚类算法实现流程

k-means其实包含两层内容:
k – 选几个中心店
means – 均值计算
流程
1、随机设置K个特征空间内的点作为初始的聚类中心
2、对于其他每个点计算到K个中心的距离,未知的点选择最近的一个聚类中心点作为标记类别
3、接着对着标记的聚类中心之后,重新计算出每个聚类的新中心点(平均值)
4、如果计算得出的新中心点与原中心点一样(质心不再移动),那么结束,否则重新进行第二步过程
kmeans小结
kmeans由于要计算质心到每一个样本的距离,所以其收敛速度比较慢

4. 模型评估【**】

(1) SSE

误差平方和
值越小越好

(2) 肘部法

下降率突然变缓时即认为是最佳的k值

(3) SC系数

取值为[-1, 1],其值越大越好

(4) CH系数

分数s高则聚类效果越好
CH需要达到的目的:用尽量少的类别聚类尽量多的样本,同时获得较好的聚类效果。

5. 算法优化【***】

(1) k_means

优点:
简单,容易理解
缺点:
特别人容易陷入到局部最优解

(2) Canopy

通过绘制同心圆,进行k值选择筛选
需要确定同心圆的半径t1,t2

(3) K-means++

距离平方进行求解
保证下一个质心到当前质心,距离最远

(4) 二分k-means

通过误差平方和,设置阈值,然后进行划分

(5) k-medoids

和kmeans选取中心点的方式不同
通过从当前点选择中心点(质心)进行判断

(6) kernel kmeans【了解】

映射到高维空间

(7) ISODATA【了解】

动态聚类
可以更改k值的大小

(8) Mini-batch K-Means【了解】

大数据集分批聚类

6. 特征降维【***】

(1) 定义

就是改变特征值,选择哪列保留,哪列删除
目标是得到一组”不相关“的主变量

(2) 降维的两种方式

特征选择
主成分分析(可以理解一种特征提取的方式)

(3) 特征选择

定义:提出数据中的冗余变量
方法:
Filter(过滤式):主要探究特征本身特点、特征与特征和目标值之间关联
方差选择法:低方差特征过滤
相关系数
Embedded (嵌入式):算法自动选择特征(特征与目标值之间的关联)
决策树:信息熵、信息增益
正则化:L1、L2
深度学习:卷积等

(4) 低方差特征过滤

把方差比较小的某一列进行剔除
api:
sklearn.feature_selection.VarianceThreshold(threshold = 0.0)
删除所有低方差特征
注意,参数threshold一定要进行值的指定

def variance_demo():
    """
    删除低方差特征——特征选择
    :return: None
    """
    data = pd.read_csv("factor_returns.csv")
    print(data)
    # 1、实例化一个转换器类
    transfer = VarianceThreshold(threshold=1)
    # 2、调用fit_transform
    data = transfer.fit_transform(data.iloc[:, 1:10])
    print("删除低方差特征的结果:\n", data)
    print("形状:\n", data.shape)

    return None

### 结果会降低一个维度,threshold = 10 则降低两个维度
(5) 相关系数

主要实现方式:
皮尔逊相关系数
斯皮尔曼相关系数

  • 皮尔逊相关系数
    通过具体值的大小进行计算
    相对复杂
    api:
    from scipy.stats import pearsonr
    返回值,越接近|1|,相关性越强;越接近0,相关性越弱
from scipy.stats import pearsonr

x1 = [12.5, 15.3, 23.2, 26.4, 33.5, 34.4, 39.4, 45.2, 55.4, 60.9]
x2 = [21.2, 23.9, 32.9, 34.1, 42.5, 43.2, 49.0, 52.8, 59.4, 63.5]

pearsonr(x1, x2)
PearsonRResult(statistic=0.9941983762371884, pvalue=4.9220899554569625e-09)
  • 斯皮尔曼相关系数
    通过等级差进行计算
    比上一个简单
    api:
    from scipy.stats import spearmanr
    返回值,越接近|1|,相关性越强;越接近0,相关性越弱
from scipy.stats import spearmanr

x1 = [12.5, 15.3, 23.2, 26.4, 33.5, 34.4, 39.4, 45.2, 55.4, 60.9]
x2 = [21.2, 23.9, 32.9, 34.1, 42.5, 43.2, 49.0, 52.8, 59.4, 63.5]

spearmanr(x1, x2)
SignificanceResult(statistic=0.9999999999999999, pvalue=6.646897422032013e-64)

7. 主成分分析 PCA

定义:
高维数据转换为低维数据,然后产生了新的变量
api:
sklearn.decomposition.PCA(n_components=None)
n_components
整数 – 表示降低到几维
小数 – 保留百分之多少的信息

from sklearn.decomposition import PCA

def pca_demo():
    """
    对数据进行PCA降维
    :return: None
    """
    data = [[2,8,4,5], [6,3,0,8], [5,4,9,1]]

    # 1、实例化PCA, 小数——保留多少信息
    transfer = PCA(n_components=0.9)
    # 2、调用fit_transform
    data1 = transfer.fit_transform(data)

    print("保留90%的信息,降维结果为:\n", data1)

    # 1、实例化PCA, 整数——指定降维到的维数
    transfer2 = PCA(n_components=3)
    # 2、调用fit_transform
    data2 = transfer2.fit_transform(data)
    print("降维到3维的结果:\n", data2)

    return None

pca_demo()
保留90%的信息,降维结果为:
 [[-3.13587302e-16  3.82970843e+00]
 [-5.74456265e+00 -1.91485422e+00]
 [ 5.74456265e+00 -1.91485422e+00]]
降维到3维的结果:
 [[-3.13587302e-16  3.82970843e+00  4.59544715e-16]
 [-5.74456265e+00 -1.91485422e+00  4.59544715e-16]
 [ 5.74456265e+00 -1.91485422e+00  4.59544715e-16]]

8. 案例:探究用户对物品类别的喜好细分降维

案例:探究用户对物品类别的喜好细分降维

import pandas as pd
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score

# 1. 获取数据
order_product = pd.read_csv(fr"./data/order_products__prior.csv")
products = pd.read_csv(fr"./data/products.csv")
orders = pd.read_csv(fr"./data/orders.csv")
aisles = pd.read_csv(fr"./data/aisles.csv")

# 2.数据基本处理
# 2.1 合并表格
table1 = pd.merge(order_product, products, on=["product_id", "product_id"])
table2 = pd.merge(table1, orders, on=["order_id", "order_id"])
table = pd.merge(table2, aisles, on=["aisle_id", "aisle_id"])

# 2.2 交叉表合并
table = pd.crosstab(table["user_id"], table["aisle"])

# 2.3 数据截取
table = table[:1000]

# 3.特征工程 — pca
transfer = PCA(n_components=0.9)
data = transfer.fit_transform(table)

# 4.机器学习(k-means)
estimator = KMeans(n_clusters=8, random_state=22)
y_predict = estimator.fit_predict(data)

# 5.模型评估
silhouette_score(data, y_predict)
  • 28
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

卡林神不是猫

如果您觉得有帮助可以鼓励小卡哦

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

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

打赏作者

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

抵扣说明:

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

余额充值