本栏目为本人自学B站各位好心的博主所录视频过程中记录下来的笔记,出处基本来自于B站视频博主以及csdn中各位大佬的解释,我只起到了转载的作用。因来源过于复杂,因此无法标注来源。
1.sklearn转换器和估计器
1.1 转换器——特征工程的父类
回顾Day1的特征工程的步骤:
- 实例化(实例化的是一个转换器类(Transformer))
- 调用fit_transform(对于文档建立分类词频矩阵,不能同时调用)
我们把特征工程的接口称之为转换器,其中转换器调用有这么几种形式
- fit_transform
- fit
- transform
比如:在进行标准化时,标准化的计算公式为(x - mean) / std
- fit_transform()
- fit() 计算每一列的平均值、标准差
- transform() (x - mean) / std进行最终的转换
1.2 估计器——sklearn机器学习算法的实现
估计器(estimator)
- 实例化一个estimator
- estimator.fit(x_train, y_train) 计算—— 调用完毕,模型生成
- 模型评估:
- 直接比对真实值和预测值
y_predict = estimator.predict(x_test)
y_test == y_predict - 计算准确率
accuracy = estimator.score(x_test, y_test)
- 直接比对真实值和预测值
2.K-近邻算法(KNN)
2.1 什么是K-近邻算法
- 定义
如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。 - KNN核心思想
通过你的“邻居”来推断出你的类别
- K-近邻算法(KNN)原理
- 若k = 1,容易受到异常点的影响
- 如何确定谁是邻居?
- 通过距离公式计算距离:
- 欧氏距离
- 曼哈顿距离 绝对值距离
- 明可夫斯基距离
- 欧氏距离
- 通过距离公式计算距离:
2.2 案例分析
电影名称 | 打斗镇头 | 接吻镜头 | 电影类型 |
---|---|---|---|
California Man | 3 | 104 | 爱情片 |
He’s not Really into dues | 2 | 100 | 爱情片 |
Beautiful Woman | 1 | 81 | 爱情片 |
Kevin Longblade | 101 | 10 | 动作片 |
Robo Slayer 3000 | 99 | 5 | 动作片 |
Amped Ⅱ | 98 | 2 | 动作片 |
? | 18 | 90 | 未知 |
其中?号电影不知道类别,如何去预测?可以使用KNN算法的思想。
电影名称 | 与未知电影的距离 |
---|---|
California Man | 20.5 |
He’s not Really into dues | 18.7 |
Beautiful Woman | 19.2 |
Kevin Longblade | 115.3 |
Robo Slayer 3000 | 117.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:鸢尾花种类预测
- 获取数据
- 数据集划分
- 特征工程
- 标准化
- KNN预估器流程
- 模型评估
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-近邻总结
- 优点:简单,易于理解,易于实现,无需训练
- 缺点:
- 必须指定K值,K值选择不当则分类精度不能保证
- 懒惰算法,对测试样本分类时的计算量大,内存开销大
- 使用场景:小数据场景,几千~几万样本,具体场景具体业务去测试
3.模型选择与调优
3.1 什么是交叉验证(cross validation)
交叉验证就是将拿到的训练数据,分为训练和验证集。以下图为例:将数据分成4份,其中一份作为验证集。然后经过4次(组)的测试,每次都更换不同的验证集。即得到4组模型的结果,取平均值作为最终结果。又称4折交叉验证。
目的:让被评估的模型更加准确可信
3.2 超参数搜索-网格搜索(Grid Search)
通常情况下,有很多参数是需要手动指定的(如k-近邻算法中的K值),这种叫超参数。但是手动过程繁杂,所以需要对模型预设几种超参数组合。每组超参数都采用交叉验证来进行评估。最后选出最优参数组合建立模型。
K值 | K=3 | K=5 | K=7 | K=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 流程分析
- 获取数据
- 数据处理
- 目的:
- 特征值 x
- 目标值 y
- a.缩小数据范围
- 2 < x < 2.5
- 1.0 < y < 1.5
- b.time -> 年月日时分秒
- c.过滤签到次数少的地点
- 数据集划分
- 目的:
- 特征工程:标准化
- KNN算法预估流程
- 模型选择与调优
- 模型评估
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 案例:新闻分类
- 获取数据
- 划分数据集
- 特征工程
- 文本特征抽取(TFIDF)
- 朴素贝叶斯预估器流程
- 模型评估
# 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 决策树分类原理详解
- 原理
- 信息熵、信息增益等
- 信息论基础
- 信息
- 香农:消除随机不定性的东西
- 小明 “我今年18岁” - 信息
- 小华 “小明明年19岁” - 不是信息
- 信息的衡量 - 信息量 - 信息熵bit
- 决策树的划分依据之一------信息增益
- 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 案例:泰坦尼克号乘客生存预测
流程分析:
- 目标:
- 特征值 目标值
- 获取数据
- 数据处理
- 缺失值处理
- 特征值 -> 字典类型
- 准备好特征值 目标值
- 划分数据集
- 特征工程:字典特征抽取
- 决策树预估器流程
- 模型评估
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_)