机器学习Day3——分类算法

本栏目为本人自学B站各位好心的博主所录视频过程中记录下来的笔记,出处基本来自于B站视频博主以及csdn中各位大佬的解释,我只起到了转载的作用。因来源过于复杂,因此无法标注来源。

1.sklearn转换器和估计器

1.1 转换器——特征工程的父类

回顾Day1的特征工程的步骤:

  1. 实例化(实例化的是一个转换器类(Transformer))
  2. 调用fit_transform(对于文档建立分类词频矩阵,不能同时调用)

我们把特征工程的接口称之为转换器,其中转换器调用有这么几种形式

  • fit_transform
  • fit
  • transform

比如:在进行标准化时,标准化的计算公式为(x - mean) / std

  • fit_transform()
    • fit() 计算每一列的平均值、标准差
    • transform() (x - mean) / std进行最终的转换

1.2 估计器——sklearn机器学习算法的实现

估计器(estimator)

  1. 实例化一个estimator
  2. estimator.fit(x_train, y_train) 计算—— 调用完毕,模型生成
  3. 模型评估:
    1. 直接比对真实值和预测值
      y_predict = estimator.predict(x_test)
      y_test == y_predict
    2. 计算准确率
      accuracy = estimator.score(x_test, y_test)

2.K-近邻算法(KNN)

2.1 什么是K-近邻算法

  • 定义
    如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
  • KNN核心思想
    通过你的“邻居”来推断出你的类别
  1. K-近邻算法(KNN)原理
    • 若k = 1,容易受到异常点的影响
  2. 如何确定谁是邻居?
    • 通过距离公式计算距离:
      • 欧氏距离
        在这里插入图片描述
      • 曼哈顿距离 绝对值距离
      • 明可夫斯基距离

2.2 案例分析

电影名称打斗镇头接吻镜头电影类型
California Man3104爱情片
He’s not Really into dues2100爱情片
Beautiful Woman181爱情片
Kevin Longblade10110动作片
Robo Slayer 3000995动作片
Amped Ⅱ982动作片
?1890未知

其中?号电影不知道类别,如何去预测?可以使用KNN算法的思想。

电影名称与未知电影的距离
California Man20.5
He’s not Really into dues18.7
Beautiful Woman19.2
Kevin Longblade115.3
Robo Slayer 3000117.4
Amped Ⅱ118.9

分析:
k = 1 爱情片
k = 2 爱情片
……
k = 6 无法确定
k = 7 动作片
如果取的最近的电影数量不一样?会是什么结果?

  • k 值取得过小,容易受到异常点的影响
  • k 值取得过大,样本不均衡的影响

结合Day1的约会对象数据,分析K-近邻算法需要做什么样的处理?

  • 做无量纲化处理,即标准化

2.3 KNN算法API

  • sklearn.neighbors.KNeighborsClassifier(n_neighbors=5,algorithm=‘auto’)
    • n_neighbors: int,可选(默认= 5) , k_neighbors查询默认使用的邻居数
    • algorithm: {‘auto’,‘ball_tree’,‘kd_tree’,‘brute’},可选用于计算最近邻居的算法: ‘ball_tree"将会使用BallTree,‘kd_tree"将使用 KDTree。"auto"将尝试根据传递给ft方法的值来决定最合适的算法。(不同实现方式影响效率)

2.4 案例1:鸢尾花种类预测

  1. 获取数据
  2. 数据集划分
  3. 特征工程
    • 标准化
  4. KNN预估器流程
  5. 模型评估
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 = train_test_split(iris.data, iris.target, random_state=22)

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

# 4)KNN算法预估器
estimator = KNeighborsClassifier(n_neighbors=3)
estimator.fit(x_train, y_train)

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

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

2.5 K-近邻总结

  1. 优点:简单,易于理解,易于实现,无需训练
  2. 缺点:
    1. 必须指定K值,K值选择不当则分类精度不能保证
    2. 懒惰算法,对测试样本分类时的计算量大,内存开销大
  3. 使用场景:小数据场景,几千~几万样本,具体场景具体业务去测试

3.模型选择与调优

3.1 什么是交叉验证(cross validation)

交叉验证就是将拿到的训练数据,分为训练和验证集。以下图为例:将数据分成4份,其中一份作为验证集。然后经过4次(组)的测试,每次都更换不同的验证集。即得到4组模型的结果,取平均值作为最终结果。又称4折交叉验证。

在这里插入图片描述

目的:让被评估的模型更加准确可信

3.2 超参数搜索-网格搜索(Grid Search)

通常情况下,有很多参数是需要手动指定的(如k-近邻算法中的K值),这种叫超参数。但是手动过程繁杂,所以需要对模型预设几种超参数组合。每组超参数都采用交叉验证来进行评估。最后选出最优参数组合建立模型。

K值K=3K=5K=7K=9
模型模型1模型2模型3模型4

3.3 模型选择与调优API

  • sklearn.model_selection.GridSearchCV(estimator,param_grid=None,cv=None)
    • 对估计器的指定参数值进行详尽搜索
    • estimator:估计器对象
    • param_grid:估计器参数(dict){“n_neighbors”:[1,3,5]}
    • cv:指定几折交叉验证
    • fit():输入训练数据
    • score():准确率
    • 结果分析:
      • 最佳参数:best_params_
      • 最佳结果:best_score_
      • 最佳估计器:best_estimator_
      • 交叉验证结果:cv_results_

3.4 鸢尾花案例增加K值调优

  • 使用GridSearchCV构建估计器
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV

# 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()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)

# 4)KNN算法预估器
estimator = KNeighborsClassifier()

# 5)加入网格搜索与交叉验证
# 参数准备
param_dict = {"n_neighbors":[1,3,5,7,9,11]}
estimator = GridSearchCV(estimator,param_grid=param_dict,cv=10)
estimator.fit(x_train, y_train)

# 6)模型评估
# 方法1:直接比对真实值和预测值
y_predict = estimator.predict(x_test)
print("y_predict:\n", y_predict)
print("直接比对真实值和预测值:\n", y_test == y_predict)

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

# 最佳参数:best_params_
print("最佳参数:\n", estimator.best_params_)
# 最佳结果:best_score_
print("最佳结果:\n", estimator.best_score_)
# 最佳估计器:best_estimator_
print("最佳估计器:\n", estimator.best_estimator_)
# 交叉验证结果:cv_results_
print("交叉验证结果:\n", estimator.cv_results_)

4.案例:预测facebook签到位置

4.1 数据集介绍

  • train.csv, test.csv
    • row_id: 登记事件的 IDxy︰坐标
    • accuracy: 定位准确性
    • time: 时间戳
    • place_id: 业务的ID,这是您预测的目标

这是来自于kaggle上的数据,地址为:https://www.kaggle.com/navoshta/grid-knn/data

4.2 流程分析

  1. 获取数据
  2. 数据处理
    • 目的:
      • 特征值 x
      • 目标值 y
      • a.缩小数据范围
        • 2 < x < 2.5
        • 1.0 < y < 1.5
      • b.time -> 年月日时分秒
      • c.过滤签到次数少的地点
      • 数据集划分
  3. 特征工程:标准化
  4. KNN算法预估流程
  5. 模型选择与调优
  6. 模型评估
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
# 1、获取数据
data = pd.read_csv("./FBlocation/train.csv")
# 2、基本的数据处理
# 	1)缩小数据范围
data = data.query("x < 2.5 & x > 2 & y < 1.5 & y > 1.0")
# 	2)处理时间特征
time_value = pd.to_datetime(data["time"], unit="s")
date = pd.DatetimeIndex(time_value)
data["day"] = date.day
data["weekday"] = date.weekday
data["hour"] = date.hour
# 	3)过滤签到次数少的地点
place_count = data.groupby("place_id").count()["row_id"]
data_final = data[data["place_id"].isin(place_count[place_count > 3].index.values)]
# 3、筛选特征值和目标值
x = data_final[["x", "y", "accuracy", "day", "weekday", "hour"]]
y = data_final["place_id"]
# 4、数据集划分
x_train, x_test, y_train, y_test = train_test_split(x, y)
# 5、特征工程:标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)

# 6、KNN算法预估器
estimator = KNeighborsClassifier()

# 7、加入网格搜索与交叉验证
# 	参数准备
param_dict = {"n_neighbors": [3, 5, 7, 9]}
estimator = GridSearchCV(estimator, param_grid=param_dict, cv=3)
estimator.fit(x_train, y_train)

# 8、模型评估
# 方法1:直接比对真实值和预测值
y_predict = estimator.predict(x_test)
print("y_predict:\n", y_predict)
print("直接比对真实值和预测值:\n", y_test == y_predict)
# 方法2:计算准确率
score = estimator.score(x_test, y_test)
print("准确率为:\n", score)

# 最佳参数:best_params_
print("最佳参数:\n", estimator.best_params_)
# 最佳结果:best_score_
print("最佳结果:\n", estimator.best_score_)
# 最佳估计器:best_estimator_
print("最佳估计器:\n", estimator.best_estimator_)
# 交叉验证结果:cv_results_
print("交叉验证结果:\n", estimator.cv_results_)

5.朴素贝叶斯算法

5.1 什么是朴素贝叶斯分类方法

是一种基于贝叶斯定理(Bayes’ theorem)的分类算法。它的基本思想是,通过先验概率和条件概率来计算后验概率,从而实现分类。

5.2 贝叶斯公式

在这里插入图片描述

5.3 为什么要称之为朴素?

其实这是一个假设:特征与特征之间是相互独立

因此,朴素贝叶斯算法可以理解为:

  • 朴素假设 + 贝叶斯公式

应用场景:

  • 文本分类
  • 单词作为特征

5.4 拉普拉斯平滑系数

引入拉普拉斯平滑系数的目的:防止计算出的分类概率为0

在这里插入图片描述
注:α为指定的系数,一般为1,m为训练文档中统计出的特征词个数

5.5 朴素贝叶斯算法API

  • sklearn.naive_bayes.MultinomialNB(alpha = 1.0)
    • 朴素贝叶斯分类
    • alpha:拉普拉斯平滑系数

5.6 案例:新闻分类

  1. 获取数据
  2. 划分数据集
  3. 特征工程
    • 文本特征抽取(TFIDF)
  4. 朴素贝叶斯预估器流程
  5. 模型评估
# 1)获取数据
news = fetch_20newsgroups(subset="all")

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

# 3)特征工程:文本特征抽取-tfidf
transfer = TfidfVectorizer()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)

# 4)朴素贝叶斯算法预估器流程
estimator = MultinomialNB()
estimator.fit(x_train, y_train)

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

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

5.7 朴素贝叶斯算法总结

  • 优点:
    • 对缺失数据不太敏感,算法也比较简单,常用于文本分类。
    • 分类准确度高,速度快
  • 缺点:
    • 由于使用了样本属性独立性的假设,所以如果特征属性有关联时其效果不好

6.决策树

6.1 认识决策树

决策树思想的来源非常朴素,也就是程序设计中的条件分支结构(if-else结构),最早的决策树就是利用这类结构分割数据的一种分类学习方法。
因此,若要高效的进行决策,则需要着重考虑特征的先后顺序

为了更好理解决策树具体怎么分类的,我们通过一个问题例子?

银行贷款数据
ID年龄有工作有自己的房子信贷情况类别
1青年一般
2青年
3青年
4青年一般
5青年一般
6中年一般
7中年
8中年
9中年非常好
10中年非常好
11老年非常好
12老年
13老年
14老年非常好
15老年一般
  • 方案1:若先看房子、再看工作,两个特征便可决定是否可以贷款
  • 方案2 :若先看年龄、再看信贷情况、最后看工作,这需要三个特征才能决定是否贷款

6.2 决策树分类原理详解

  1. 原理
  • 信息熵、信息增益等
  1. 信息论基础
    1. 信息
      • 香农:消除随机不定性的东西
      • 小明 “我今年18岁” - 信息
      • 小华 “小明明年19岁” - 不是信息
    2. 信息的衡量 - 信息量 - 信息熵bit
      在这里插入图片描述
    3. 决策树的划分依据之一------信息增益
      • g(D,A) = H(D) - 条件熵H(D|A)

在这里插入图片描述

6.3 决策树分类算法API

  • class sklearn.tree.DecisionTreeClassifier(criterion="gini’,max_depth=None,random_state=None)
    • 决策树分类器
    • criterion:默认是’gini’系数,也可以选择信息增益的熵’entropy’
    • max_depth:树的深度大小
    • random_state:随机数种子

6.4 决策树的可视化

  • sklearn.tree.export_graphviz(该函数能够导出DOT格式
    • tree.export_graphviz(estimator,out_file=‘tree.dot’,feature_names=[“,”])

dot文件可视化:http://webgraphviz.com/

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

流程分析:

  • 目标:
    • 特征值 目标值
  1. 获取数据
  2. 数据处理
    • 缺失值处理
    • 特征值 -> 字典类型
  3. 准备好特征值 目标值
  4. 划分数据集
  5. 特征工程:字典特征抽取
  6. 决策树预估器流程
  7. 模型评估
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier,export_graphviz

# 1.获取数据
resource_data = pd.read_csv("./data/titanic.csv")

# 2.选择特征值和目标值
x = resource_data[["pclass","age","sex"]]
y = resource_data["survived"]

# 3.数据处理
# 3.1 缺失值处理
x["age"].fillna(x["age"].mean(),inplace=True)
# 3.2 转换成字典
x = x.to_dict(orient="records")

# 4.划分数据集
x_train,x_test,y_train,y_test = train_test_split(x,y,random_state=10)

# 5.特征工程:特征抽取
transfer = DictVectorizer()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)

# 6.决策树预估器
estimator = DecisionTreeClassifier(criterion="entropy")
estimator.fit(x_train,y_train)

# 7.模型评估
# 7.1 直接对比真实值和预估值
prediction = estimator.predict(x_test)
print("真实值与预估值对比结果:",prediction == y_test)
# 7.2 计算准确率
score = estimator.score(x_test,y_test)
print("预估准确率为:",score)

# 8.决策树可视化
export_graphviz(estimator, out_file="titanic_tree.dot", feature_names=transfer.get_feature_names_out())

6.6 决策树总结

  • 优点:
    • 可视化 - 可解释能力强
  • 缺点:
    • 容易产生过拟合
  • 改进;
    • 减枝cart算法(决策树API当中已经实现,随机森林参数调优有相关介绍)
    • 随机森林

7.集成学习方法与随机森林

7.1 什么是集成学习方法

集成学习通过建立几个模型组合的来解决单―预测问题。它的工作原理是生成多个分类器/模型,各自独立地学习和作出预测。这些预测最后结合成组合预测,因此优于任何一个单分类的做出预测。

7.2 什么是随机森林

在机器学习中,随机森林是一个包含多个决策树的分类器,并且其输出的类别是由个别树输出的类别的众数而定。

7.3 随机森林原理过程

根据下列算法而建造每棵树:

  • 用N来表示训练用例(样本)的个数,M表示特征数目。
    • 1 一次随机选出一个样本,重复N次(有可能出现重复的样本)
    • 2 随机去选出m个特征, m <<M,建立决策树
  • 采取bootstrap抽样

两种随机:

  • 训练集随机 - N个样本中随机有放回的抽样N个
    • bootstrap 随机有放回 抽样
  • 特征随机 - 从M个特征中随机抽取m个特征
    • M >> m
    • 降维

为什么采用BootStrap抽样

  • 为什么要随机抽样训练集?
    • 如果不进行随机抽样,每棵树的训练集都一样,那么最终训练出的树分类结果也是完全一样的
  • 为什么要有放回地抽样?
    • 如果不是有放回的抽样,那么每棵树的训练样本都是不同的,都是没有交集的,这样每棵树都是"有偏的",都是绝对“片面的"y(当然这样说可能不对),也就是说每棵树训练出来都是有很大的差异的;而随机森林最后分类取决于多棵树(弱分类器)的投票表决。

7.4 随机森林分类算法的API

sklearn.ensemble.RandomForestClassifier(n_estimators=10,criterion=‘gini’,max_depth=None, bootstrap=True, random_state=None, min_samples_split=2)

  • 随机森林分类器
  • n_estimators: integer,optional (default = 10)森林里的树木数量120,200,300,500,800,1200
  • criteria: string,可选(default =“gini")分割特征的测量方法
  • max_depth: integer或None,可选(默认=无)树的最大深度5,8,15,25,30
  • max_featuresm “auto”",每个决策树的最大特征数量
    • lf “auto”, then max_features=sqrt(n_features) .
    • If “sqrt” , then max_features=sqrt(n_features) (same as “auto”).
    • If “log2” , then max_features=log2(n_features) .
    • lf None, then max_features=n_features .
  • bootstrap: boolean,optional (default = True)是否在构建树时使用放回抽样
  • min_samples_split:节点划分最少样本数
  • min_samples_leaf:叶子节点的最小样本数

超参数:n_estimator, max_depth,min_samples_split,min_samples_leaf

7.5 总结

  • 在以上所有算法中,具有极好的准确率
  • 能够有效地运行在大数据集上,处理具有高维特征的输入样本,而且不需要降维
  • 能够评估各个特征在分类问题上的重要性

7.6 案例训练

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

# 1.获取数据
resource_data = pd.read_csv("./data/titanic.csv")

# 2.选择特征值和目标值
x = resource_data[["pclass","age","sex"]]
y = resource_data["survived"]

# 3.数据处理
# 3.1 缺失值处理
x["age"].fillna(x["age"].mean(),inplace=True)
# 3.2 转换成字典
x = x.to_dict(orient="records")

# 4.划分数据集
x_train,x_test,y_train,y_test = train_test_split(x,y,random_state=10)

# 5.特征工程:特征抽取
transfer = DictVectorizer()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)

# 6.随机森林预估器
estimator = RandomForestClassifier()

# 7.模型选择与调优
param_dict = {"n_estimators":[60,120,200,300,500,800,1200],"max_depth":[5,8,15,25,30]}
estimator = GridSearchCV(estimator,param_grid=param_dict,cv=5)
estimator.fit(x_train,y_train)

# 8.模型评估
# 8.1 直接对比真实值和预估值
prediction = estimator.predict(x_test)
print("真实值与预估值对比结果:",prediction == y_test)
# 8.2 计算准确率
score = estimator.score(x_test,y_test)
print("预估准确率为:",score)

# 最佳参数:best_params_
print("最佳参数:\n", estimator.best_params_)
# 最佳结果:best_score_
print("最佳结果:\n", estimator.best_score_)
# 最佳估计器:best_estimator_
print("最佳估计器:\n", estimator.best_estimator_)
# 交叉验证结果:cv_results_
print("交叉验证结果:\n", estimator.cv_results_)

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值