1、朴素贝叶斯算法
1.1 概率基础
1.1.1 联合概率
包含多个条件,且所有条件同时成立的概率
记作:P(A,B) = P(A) * P(B)
1.1.2 条件概率
事件A在满足事件B的前提下发生的概率
记作:P(A|B)
P(A1,A2|B) = P(A1|B)P(A2|B)
注意: 此条件概率的成立前提是A1,A2相互独立,即A1,A2两个特征之间不互相影响
1.2 朴素贝叶斯
朴素贝叶斯最常用于文档分类,使用算法的前提条件是特征独立
朴素贝叶斯-贝叶斯公式
注:w为给定文档的特征值,c为文档类别
公式可以理解为:
公式分为三个部分,其中c可以是不同类别
- P( C ):某个文档类别的概率 = 某文档类别词数 / 总文档词数
- P(W│C):给定类别下特征(被预测文档中出现的词)的概率
计算方法:P(Fi│C)=Ni/N(训练文档中去计算)
Ni为词Fi在C类别所有文档中出现的次数
N为所属类别C下的文档所有词出现的次数和 - P(F1,F2,…):预测文档中每个词的概率
e.g
属于某个类别的概率为0不合理!!!
1.2.1 拉普拉斯平滑
从以上例子得到为娱乐类概率是0,这不合理。如果词频列表里其他词在娱乐类出现概率很高,但个别词没有在娱乐类中出现,整体概率计算得到0,可能出现分类错误,解决方法拉普拉斯平滑系数。
拉普拉斯平滑
- P(F1│C)=(Ni+α)/(N+αm)
- α为指定的系数默认值为1,m为训练文档中统计出的特征词个数。
经过拉普拉斯平滑处理,上一案例则变为
1.2.2 朴素贝叶斯API
sklearn朴素贝叶斯API:sklearn.naive_bayes.MultinomialNB(alpha = 1.0)
- alpha:拉普拉斯平滑系数,默认为1
1.2.3 20类新闻分类案例
sklearn20类新闻分类:20个新闻组数据集包含20个主题的18000个新闻组帖子
流程:
1、加载20类新闻数据,并进行分割
2、生成文章特征词
3、朴素贝叶斯estimator流程进行预估
from sklearn.naive_bayes import MultinomialNB
from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import classification_report
def NB():
'''
朴素贝叶斯算法分类,按类别概率大小确认类别
:return: None
'''
# 1.加载数据
news = fetch_20newsgroups(subset='all')
data = news.data # 特征值
target = news.target # 目标值
# 2.分割数据集
x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.25)
# 3.特征工程,重要性文本特征抽取
tf = TfidfVectorizer()
# 以训练集当中的词的列表进行每篇文章词的重要性统计
x_train = tf.fit_transform(x_train)
print(tf.get_feature_names()) # 特征字段名
x_test = tf.transform(x_test)
# 4.进行朴素贝叶斯算法预测
nb = MultinomialNB(alpha=1.0)
nb.fit(x_train, y_train)
y_predict = nb.predict(x_test)
print('测试集的预测值为:', y_predict)
print('测试集预测的准确率为:', nb.score(x_test, y_test))
# target_names文章类别的字符串
print('每个类别的精确率与召回率:', classification_report(y_test, y_predict, target_names=news.target_names))
return None
if __name__ == "__main__":
NB()
1.2.4 总结
优点:
- 朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率
- 对缺失数据不太敏感,算法也比较简单,常用于文本分类
- 数据量大的情况下,分类准确度高,速度快
- 朴素贝叶斯算法不需要调超参数
缺点:
- 概率P(C|F1,F2,…) = P(F1,F2,…|C)P( C )/P(F1,F2,…)的前提条件是特征独立。朴素贝叶斯算法假设文章中出现的词语之间是独立关系,但有些词语之间有一定联系,则假设不成立,从而导致预测效果不佳。
- 朴素贝叶斯算法准确率取决于训练集的选择。训练集文章更具有代表性、重要性特征词的选择更准确,都会提高算法的准确性。
2、分类模型的评估
2.1 estimator.score()
最常见使用的是准确率,即预测结果正确的百分比
2.2 混淆矩阵
在分类任务下,每一个目标值的预测结果(Predicted Condition)与正确标记(True Condition)之间存在四种不同的组合,构成混淆矩阵。
2.2.1 精确率(Precision)与召回率(Recall)
- 精确率:预测结果为正例样本中真实为正例的比例(查得准)
- 召回率:真实为正例的样本中预测结果为正例的比例(查的全,对正样本的区分能力)
- F1-score,反映了模型的稳健型
2.3 分类模型评估API
分类模型评估API:sklearn.metrics.classification_report(y_true, y_pred, target_names=None)
- y_true:真实目标值
- y_pred:估计器预测目标值
- target_names:目标类别名称
- return:每个类别精确率与召回率
3、模型的选择与调优
3.1 交叉验证
交叉验证的目的是为了让被评估的模型更加准确、可信。
交叉验证作为网格搜索的参数,与网格搜索一起使用进行参数调优。
交叉验证先将数据自定义成n等分,选其中一份作为验证集(验证集与测试集无关),其余n-1份作为训练集,得出该组准确率。经过n次操作得出n组准确率的平均值作为最终准确率。这种方法称为n折交叉验证,最常用的是10折交叉验证。
以下图为例:
将数据分成5等份,其中一份作为验证集。然后经过5组测试,每次都更换不同的验证集,得到5组模型的准确率结果。取5组模型准确率的平均值作为最终结果,称为5折交叉验证。
3.2 网格搜索
3.2.1 超参数搜索–网格搜索
通常情况下,有很多参数需要被指定(如k-近邻算法中的K值),此类参数叫超参数。但是手动指定繁杂,所以模型预设了几种超参数组合,每组超参数都采用交叉验证来进行评估,最后选出最优参数组合建立模型。
3.2.2 超参数搜索–网格搜索API
超参数搜索-网格搜索API:sklearn.model_selection.GridSearchCV(estimator, param_grid=None,cv=None)
对估计器的指定参数值进行详尽搜索
- estimator:估计器对象,如kn,kn=KNeighborsClassifier()
- param_grid:估计器参数(字典格式传入),如param_grid = {“n_neighbors”:[1,3,5]}
- cv:指定几折交叉验证,最常使用10折交叉验证
- .fit(x_train,y_train):输入训练数据
- .score(x_test,y_test):预测准确率
结果分析:
- .best_score_:在交叉验证中测试的最好准确率结果
- .best_estimator_:最优参数模型
- .cv_results_:每次交叉验证后的验证集准确率结果和训练集准确率结果
3.2.3 K-近邻网格搜索案例
K近邻算法实例:预测入住位置
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
import pandas as pd
def knn():
'''
k近邻算法:预测用户签到位置
:return: None
'''
data = pd.read_csv(r".\data\02.facebook-v-predicting-check-ins\train.csv")
# print(data.head(10))
data = data.query('x>1.0 & x<1.25 & y>2.5 & y<2.75')
time_value = pd.to_datetime(data['time'], unit='s')
time_key = pd.DatetimeIndex(time_value)
data['day'] = time_key.day
data['hour'] = time_key.hour
data['weekday'] = time_key.weekday
data = data.drop(['time'], axis=1)
# print(data.head(10))
place_count = data.groupby('place_id').count()
# print(place_count.head(10))
place_nid = place_count[place_count['row_id'] > 3].index
# print(place_nid)
data = data[data['place_id'].isin(place_nid)]
# print(data)
y = data['place_id']
x = data.drop(['place_id', 'row_id'], axis=1)
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)
std = StandardScaler()
x_train = std.fit_transform(x_train)
x_test = std.transform(x_test)
# 进行算法流程
knn = KNeighborsClassifier() # 用网格搜索进行调参,在实例化算法时不设定参数
# 构造一些参数的值进行搜索
param = {
'n_neighbors': [3, 5, 10]}
# 进行网格搜索
cv = GridSearchCV(knn, param_grid=param, cv=10) # 通过10折交叉验证和网格搜索,优选参数n_neighbors
cv.fit(x_train, y_train)
print('测试集的准确率为:', cv.score(x_test, y_test))
print('在交叉验证中测试的最好结果:', cv.best_score_)
print('最好的参数模型:', cv.best_estimator_)
print('各个超参数每次交叉验证的结果:', cv.cv_results_)
return None
if __name__ == '__main__':
knn()
4、 决策树、随机森林
4.1 决策树
决策树程序设计中的条件分支结构就是if-then结构,最早的决策树就是利用这类结构分割数据的一种分类学习方法。
4.1.1 信息熵
H的专业术语称之为信息熵,表示不确定信息量,单位为比特。信息熵在传送压缩中用的比较多,信息熵越大则信息不确定性越大,信息和消除不确定性是相联系的。
公式:H = -(p1logp1 + p2logp2 + … + p32log32)
4.1.2 决策树的划分依据之一:信息增益
特征A对训练数据集D的信息增益g(D,A),定义为集合D的信息熵H(D)与特征A给定条件下D的信息条件熵H(D|A)之差,即公式为:
注:决策树分类特征的先后顺序由减少不确定性的大小来排序,信息增益即表示得知一个特征条件之后,减少不确定(信息熵)的⼤小。
e.g
目标值结果分类成是/否,则总体熵:H(D) = -(9/15log9/15 + 6/15log(6/15))=0.971
年龄作为第一个特征条件时的信息增益:
g(D, 年龄) = H(D) - H(D|年龄) =0.971- [1/3H(⻘年)+1/3H(中年)+1/3H(老年)]=0.083
- H(青年) = -(2/5log(2/5)+ 3/5log(3/5))=0.971
- H(中年) = -(2/5log(2/5)+ 3/5log(3/5))=0.971
- H(老年) = -(4/5log(4/5)+ 1/5log(1/5))=0.722
同理: g(D, 工作)=0.324,g(D, 房子)=0.420,g(D, 信用)=0.363
g(D, 房子)的信息增益最大,所以以房子作为首要特征(第一个判定标准)
4.1.3 常见决策树使用的算法
ID3:信息增益最大的准则
C4.5:信息增益比最大的准则
CART:
- 回归树: 平方误差最小
- 分类树: 基尼系数最小的准则(sklearn中的默认划分原则,其划分更加仔细且准确)
4.1.4 sklearn决策树API
sklearn.tree.DecisionTreeClassifier(criterion=’gini’, max_depth=None,random_state=None)
- criterion:默认是’gini’系数,也可以选择信息增益熵’entropy’
- max_depth:树的深度,是个自定义超参数,取值会影响预测准确率
- random_state:随机数种子
4.1.5 本地保存决策树的结构
sklearn.tree.export_graphviz(estimator,out_file=‘路径/文件.dot’,feature_names=[’’,…])
导出DOT格式决策树结构(二进制格式)
- estimator:估计器
- out_file:输出的存储路径+文件名
- feature_names:指定各节点显示的名字
安装graphviz(将dot文件转换为pdf、png)
pip install graphviz
运行命令(将二进制文件转换成图片)
dot -Tpng 文件名.dot -o 文件名.png
4.1.6 泰坦尼克号乘客生存分类案例
泰坦尼克号乘客生存分类案例:(pclass的1st,2st,3st代表社会经济阶层,其中age数据存在缺失)
流程:
- pd读取数据
- 选择有影响的特征,处理缺失值
- 分割训练集与测试集
- 进行特征工程(pd按记录逐行转换字典格式数据,x_train.to_dict(orient=“records”),转换后将分类字段进行字典特征值抽取)
- 决策树估计器流程
import pandas as pd
from sklearn.feature_extraction import DictVectorizer
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
# 决策树算法的一大优点,可以导出树结构
from sklearn.tree import export_graphviz
def decision():
'''
用决策树算法,预测泰坦尼克号乘客生存情况
:return:None
'''
# 1. 获取数据
titan = pd.read_csv(r"E:\working\Pycharm_project\machine_learn\data\03.Titanic\train.csv")
# print(titan)
# 2. 处理数据,找出特征值与目标值
x = titan[['Pclass', 'Age', 'Sex']] # 特征值
y = titan['Survived'] # 目标值
# print(x)
# age缺失值处理,null与任意值运算都为null
x['Age'].fillna(x['Age'].mean(), inplace=True) # inplace=True,用均值替换原先null值
# 3. 分割训练集与测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)
# 4. 特征工程:'pclass'和'sex'为string类型,是类别需要用one_hot编码进行处理
dict = DictVectorizer(sparse=False) # 返回ndarray数组
x_train_dict = x_train.to_dict(orient='records')
x_test_dict = x_test.to_dict(orient='records')
# orient='records'将数据按每条记录转换成字典格式,字典特征抽取分类string数据
# print(x_train_dict)
x_train = dict.fit_transform(x_train_dict)
print(dict.get_feature_names())
x_test = dict.transform(x_test_dict)
#print(x_train) # 转换成字典后的训练集特征值
# 5. 运行决策树算法
tree = DecisionTreeClassifier()
# 分类特征值都是转化为字典形的数据
tree.fit(x_train, y_train)
print('预测的准确率为:', tree.score(x_test, y_test))
# 导出决策树的结构,feature_names指定展示的节点名
# 需要安装graphviz(将dot二进制文件转换为pdf/png)
export_graphviz(tree, out_file=r".\data\03.Titanic\decision_tree.dot",
feature_names=['年龄', '社会等级', '女性', '男性'])
return None
if __name__ == '__main__':
decision()
4.1.7 决策树的优缺点以及改进
优点:
- 原理简单,条件分类
- 决策树结构可导出从而实现可视化,更直观、清晰
- 对数值型数据前期准备简单,无强制标准化要求
- 能够评估各个特征在分类问题上的重要性(分类条件约靠上,信息增益越大)
缺点:
- 训练集得出的复杂决策树用于测试集未必预测准确率高,可能存在过拟合情况
- 决策树不稳定,数据的小变化可能生成完全不同的树
改进:
- 减枝cart算法
决策树的参数可以设置枝干上样本数的下限,从而达成减枝效果和减小异常值对树影响。
- 随机森林
4.2 集成学习方法-随机森林
集成学习通过建立几个模型组合,来解决单一预测问题。工作原理是生成多个分类器/模型,各自独立地学习和作出预测。这些预测最后结合成单预测,因此优于任何一个单分类的做出预测。
在机器学习中,随机森林是一个包含多个决策树(用不同训练集建立起来的不同决策树)的分类器,并且其输出的类别是由个别树输出的类别的众数而定。
4.2.1 建⽴多个决策树的过程
单个树的建⽴过程:(总共N个样本, M个特征)
- 随机在N个样本中以有放回抽样的方式,取样N次,形成一个训练集(即bootstrap取样),样本数据有可能重复。
- 随机在M个特征中选出m个特征(m<<M)
注意:随机抽样是为了避免每一棵决策树模型都一样;有放回的抽样则是为了保证每棵决策树之间有交集,使得最终输出的众数有说服力。
4.2.2 集成学习-随机森林API
sklearn.ensemble.RandomForestClassifier(n_estimators=10,criterion=‘gini’,max_depth=None,bootstrap=True,random_state=None)
- n_estimators:可选,默认n_estimators = 10,随机森林里的决策树的数量
经验值:120,200,300,500,800,1200 - criteria:可选,默认criterion=‘gini’,分割特征的方法,基尼系数划分更仔细且准确
- max_depth:可选,默认max_depth=None,树的最大深度,是个超参数
经验值:5,8,15,25,30 - bootstrap:可选,默认bootstrap=True,是否在构建树时使用有放回抽样
- max_features:每棵决策树的最大特征数量,处理过拟合情况
max_features=‘auro’:最大特征数量不超过sqrt(总特征数量)
max_features=‘log2’:最大特征数量不超过log2(总特征数量)
max_features=‘None’:最大特征数量不超过总特征数量
4.2.3 泰坦尼克号乘客生存分类案例
import pandas as pd
from sklearn.feature_extraction import DictVectorizer
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
def random_forest():
'''
随机森林+网格搜索参数调优
:return:None
'''
titan = pd.read_csv(r".\data\03.Titanic\train.csv")
x = titan[['Pclass', 'Age', 'Sex']] # 特征值
y = titan['Survived'] # 目标值
x['Age'].fillna(x['Age'].mean(), inplace=True)
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)
dict = DictVectorizer(sparse=False)
x_train_dict = x_train.to_dict(orient='records')
x_test_dict = x_test.to_dict(orient='records')
x_train = dict.fit_transform(x_train_dict)
x_test = dict.transform(x_test_dict)
# 随机森林进行预测(网格搜索进行超参数调优)
rf = RandomForestClassifier()
# 网格搜索调优
# 需要调优的参数
param = {
'n_estimators': [120, 200, 300, 500, 800, 1200], 'max_depth': [5, 8, 15, 25, 30]}
gc = GridSearchCV(rf, param_grid=param, cv=10)
gc.fit(x_train, y_train)
print('预测准确率为:', gc.score(x_test, y_test))
print('查看选择的参数模型:', gc.best_params_)
return None
if __name__ == '__main__':
random_forest()
注意:随机森林不支持导出决策树结构
4.2.4 随机森林的优点
- 具有极好的准确率
- 能够有效地运行在大数据集上(大样本+大特征数)
- 能够处理高维特征的数据集,而且不需要降维
转载:https://blog.csdn.net/weixin_44454872/article/details/116297508