k近邻算法与朴素贝叶斯算法

机器学习——k近邻算法与朴素贝叶斯算法

  • k近邻算法
  • 朴素贝叶斯
    • 理论基础:
  • 精确率和召回率
  • 交叉验证与网格搜索

k近邻算法

定义:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别
计算距离公式:利用欧式距离定义 ( a 1 − b 1 ) 2 + . . . + ( a n − b n ) 2 \sqrt{(a_1-b_1)^2+...+(a_n-b_n)^2} (a1b1)2+...+(anbn)2

由上述公式可看出k近邻算法需要进行标准化处理

  • 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’将尝试根据传递给fit方法的值来决定最合适的算法。 (不同实现方式影响效率)
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors = 5)
knn.fit(x_train, y_train)
y_predict = knn.predict(x_test) # 根据测试集得出预测结果
knn.score(x_test, y_test) # 根据测试集得出准确率

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

朴素贝叶斯

理论基础:

贝叶斯公式: P ( C ∣ W ) = P ( W ∣ C ) P ( C ) P ( W ) P(C|W) = \frac{P(W|C)P(C)}{P(W)} P(CW)=P(W)P(WC)P(C)
注:W为给定文档的特征值(频数统计,预测文档提供),C为文档类别

  • 公式分为三个部分:
    • P ( C ) P(C) P(C):每个文档类别的概率(某文档类别词数/总文档词数)
    • P ( W ∣ C ) P(W|C) P(WC) 给定类别下特征(被预测文档中出现的词)的概率

计算出每个类别的后验概率,选取概率最大的作为其类别。

计算方法 P ( F 1 │ C ) = N i / N P(F_1│C)=N_i/N P(F1C)=Ni/N (训练文档中去计算, N i N_i Ni为该 F 1 F_1 F1词在C类别所有文档中出现的次数,N为所属类别C下的文档所有词出现的次数和, P ( F 1 , F 2 , . . . ) P(F_1,F_2,...) P(F1,F2,...):预测文档中每个词的概率。

问题:有时得到一些类别的概率为0,这是不合理的,如果词频列表里面有很多出现次数都为0,很可能计算结果都为零。
解决办法:拉普拉斯平滑系数
P ( F 1 ∣ C ) = N i + α N + α m P(F_1|C)=\frac{N_i+\alpha}{N+\alpha m} P(F1C)=N+αmNi+α α \alpha α为指定的系数,一般取为1,m为训练文档中统计出的特征词个数。

sklearn朴素贝叶斯实现API:sklearn.naive_bayes.MultinomialNB

  • sklearn.naive_bayes.MultinomialNB(alpha = 1.0)
    • 朴素贝叶斯分类
    • α \alpha α:拉普拉斯平滑系数
from sklearn.naive_bayes import MultinomialNB
news = fetch_20newsgroups(subset='all') # 导入数据集

# 进行数据集分割
x_train, x_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.25)

# 对数据集进行特征抽取
tf = TfidfVectorizer()
# 以训练集当中的词的列表进行每篇文章重要性统计
x_train = tf.fit_transform(x_train)
x_test = tf.transform(x_test)

# 进行朴素贝叶斯算法的预测
mlt = MultinomialNB(alpha=1.0)
mlt.fit(x_train, y_train)

y_predict = mlt.predict(x_test)
mlt.score(x_test, y_test)

算法分析

  • 优点:
    • 朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率。
    • 对缺失数据不太敏感,算法也比较简单,常用于文本分类。
    • 分类准确度高,速度快
  • 缺点:
    • 需要知道先验概率 P ( F 1 , F 2 , … ∣ C ) P(F_1,F_2,…|C) P(F1,F2,C),因此在某些时候会由于假设的先验模型的原因导致预测效果不佳。

精确率和召回率

精确率:预测结果为正例样本中真实为正例的比例(查得准)
召回率:真实为正例的样本中预测结果为正例的比例(查的全,对正样本的区分能力)

分类模型评估API:sklearn.metrics.classification_report

  • sklearn.metrics.classification_report(y_true, y_pred, target_names=None)
    • y_true: 真实目标值
    • y_pred: 估计器预测目标值
    • target_names: 目标类别名称
    • return: 每个类别精确率与召回率
from sklearn.metrics import classification_report
print(classification_report(y_test, y_predict, target_names=news.target_names))

交叉验证与网格搜索

交叉验证:为了让被评估的模型更加准确可信。
交叉验证过程:将拿到的数据,分为训练和验证集。例如将数据分成5份,其中一份作为验证集。然后经过5次(组)的测试,每次都更换不同的验证集。即得到5组模型的结果,取平均值作为最终结果。又称5折交叉验证。
网格搜索:通常情况下,有很多参数是需要手动指定的(如k-近邻算法中的K值),这种叫超参数。但是手动过程繁杂,所以需要对模型预设几种超参数组合。每组超参数都采用交叉验证来进行评估。最后选出最优参数组合建立模型。

网格搜索API:sklearn.model_selection.GridSearchCV

  • sklearn.model_selection.GridSearchCV(estimator, param_grid=None, cv=None)
    • 对估计器的指定参数值进行详尽搜索
    • estimator:估计器对象
    • param_grid:估计器参数(dict){“n_neighbors”: [1,3,5]}
    • cv:指定几折交叉验证
    • fit:输入训练数据
    • score:准确率
    • 结果分析:
    • best_score_:在交叉验证中测试的最好结果
    • best_estimator_:最好的参数模型
    • cv_results_:每次交叉验证后的测试集准确率结果和训练集准确率结果
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
knn = KNeighborsClassifier()

# 构造一些参数的值进行搜索
param = {"n_neighbors": [3, 5, 10]}

# 进行网格搜索
gc = GridSearchCV(knn, param_grid=param, cv=10)
gc.fit(x_train, y_train)

# 预测准确率
print("在测试集上准确率:", gc.score(x_test, y_test))
print("在交叉验证当中最好的结果:", gc.best_score_)
print("选择最好的模型是:", gc.best_estimator_)
print("每个超参数每次交叉验证的结果:", gc.cv_results_)

你可能感兴趣的:(k近邻算法与朴素贝叶斯算法)