k近邻算法,朴素贝叶斯算法,分类模型评估,模型调优

k近邻算法

k近邻算法概述
  1. k近邻算法的定义
    如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别
  2. 距离计算公式
    两个样本的距离可以通过如下公式计算,又叫欧式距离
    若点a,b坐标如下:a(a1,a2,a3),b(b1,b2,b3)
    则点a,b间的距离计算公式如下:
    在这里插入图片描述
k近邻算法代码实现
  1. 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’将尝试根据传递给fit方法的值来决定最合适的算法。 (不同实现方式影响效率)
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler

def knncls():

# 读取数据
    data = pd.read_csv(r"E:\data\facebook-v-predicting-check-ins\train.csv\train.csv")

# 缩小数据集范围
    data = data.query("x>1.0&x<1.25&y>1.0&y<1.25")

    # print(data.head(10))

# 把时间戳特征转化为天、小时、周,删除时间戳特征
    time_value = pd.to_datetime(data['time'],unit='s')
    # print(type(time_value))
    time_value = pd.DatetimeIndex(time_value)
    data['day'] = time_value.day
    data['hour'] = time_value.hour
    data['weekday'] = time_value.weekday
    data = data.drop(['time'],axis =1)
    print(data.head(10))

# 减少目标值个数,把签到数量小于3的目标位置删除
    place_count = data.groupby('place_id').count()
    tf = place_count[place_count.row_id>3].reset_index()
    data = data[data['place_id'].isin(tf.place_id)]

# 取出特征值和目标值
    y = data['place_id']
    x = data.drop(['place_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.fit_transform(x_test)

# knn算法流程
    knn = KNeighborsClassifier()
    knn.fit(x_train,y_train)
    y_predict = knn.predict(x_test)
    print("预测目标签到位置为:",y_predict)
    print(knn.score(x_test,y_test))

    return None

if __name__ == '__main__':
    knncls()

输出结果:

  row_id       x       y  accuracy    place_id  day  hour  weekday
2450    2450  1.2427  1.1598       224  6026000998    5    21        0
2636    2636  1.0256  1.0355       148  5152560199    9    19        4
2766    2766  1.0814  1.0391        70  8517315303    6    20        1
3164    3164  1.0442  1.0195       117  5152560199    6    18        1
3342    3342  1.0528  1.0103         9  1109153906    1    15        3
4755    4755  1.2161  1.0410       123  8330850914   10     1        5
6245    6245  1.0204  1.0027        20  2013736336    2    22        4
7675    7675  1.2380  1.0588        83  6852043069    8    23        3
8082    8082  1.0081  1.1633       165  5028377747    8    17        3
9565    9565  1.1783  1.0316         7  5887940395    3    23        5


预测目标签到位置为: [2229770936 2229770936 4338348850 ... 1650177003 8765197091 1985125281]
0.33544093178036605
k近邻算法的评价
  1. k取不同值时对算法性能的影响
    k值取很小:容易受异常点影响
    k值取很大:容易受最近数据太多导致比例变化
  2. k近邻算法优缺点
    优点:简单,易于理解,易于实现,无需估计参数,无需训练
    缺点:1)懒惰算法,对测试样本分类时的计算量大,内存开销大;2)必须指定K值,K值选择不当则分类精度不能保证
  3. 使用场景:小数据场景

朴素贝叶斯算法

朴素贝叶斯算法概述

以贝叶斯公式为概率基础的模型,前提条件为事件之间相互独立

朴素贝叶斯代码实现
  1. API: sklearn.naive_bayes.MultinomialNB(alpha = 1.0)
    朴素贝叶斯分类
    alpha:拉普拉斯平滑系数
import pandas as pd
from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB


def naviebayes():

    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()

    # 转化为one-hot编码
    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)
    print("预测的文章类别为:", y_predict)
    print("准确率为:", mlt.score(x_test,y_test))


    return None


if __name__ == '__main__':
    naviebayes()

输出结果:

预测的文章类别为: [11 14  6 ... 17  3  7]
准确率为: 0.8404074702886248
朴素贝叶斯的评价

优点:

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

分类模型的评估

分类模型评估概述
  1. estimator.score()
    一般最常见使用的是准确率,即预测结果正确的百分比
  2. 其他评价指标:精确率(Precision),召回率(Recall),F1-score
  • 精确率:预测结果为正例样本中真实为正例的比例(查得准)
  • 召回率:真实为正例的样本中预测结果为正例的比例(查的全,对正样本的区分能力)
  • F1-score:反映了模型的稳健性
分类模型评估代码实现
  1. API:sklearn.metrics.classification_report(y_true, y_pred, target_names=None)
    y_true:真实目标值
    y_pred:估计器预测目标值
    target_names:目标类别名称
    return:每个类别精确率与召回率
  2. 以文本分类为例的模型评估
import pandas as pd
from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report


def naviebayes():

    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()

    # 转化为one-hot编码
    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)
    print("预测的文章类别为:", y_predict)
    print("准确率为:", mlt.score(x_test,y_test))
    print("每个类别的精确率和召回率:",classification_report(y_test,y_predict,target_names=news.target_names))

    return None


if __name__ == '__main__':
    naviebayes()

输出结果:

预测的文章类别为: [15 15 10 ... 17  4  7]
准确率为: 0.849320882852292
每个类别的精确率和召回率:                           precision    recall  f1-score   support

             alt.atheism       0.95      0.65      0.77       223
           comp.graphics       0.87      0.79      0.83       225
 comp.os.ms-windows.misc       0.89      0.85      0.87       245
comp.sys.ibm.pc.hardware       0.75      0.85      0.80       246
   comp.sys.mac.hardware       0.90      0.86      0.88       234
          comp.windows.x       0.96      0.85      0.90       254
            misc.forsale       0.92      0.75      0.83       246
               rec.autos       0.89      0.94      0.92       224
         rec.motorcycles       0.94      0.95      0.95       252
      rec.sport.baseball       0.96      0.96      0.96       267
        rec.sport.hockey       0.92      0.98      0.95       243
               sci.crypt       0.73      0.98      0.83       238
         sci.electronics       0.91      0.77      0.83       251
                 sci.med       0.98      0.84      0.91       279
               sci.space       0.90      0.95      0.92       252
  soc.religion.christian       0.46      0.98      0.63       221
      talk.politics.guns       0.84      0.95      0.89       247
   talk.politics.mideast       0.91      0.97      0.94       236
      talk.politics.misc       0.99      0.66      0.79       173
      talk.religion.misc       0.96      0.15      0.27       156

               micro avg       0.85      0.85      0.85      4712
               macro avg       0.88      0.83      0.83      4712
            weighted avg       0.88      0.85      0.85      4712

模型的调优

相关概念
交叉验证
  1. 目的:为了让被评估的模型更加准确可信
  2. 交叉验证过程:将拿到的数据,分为训练和验证集。以下图为例:将数据分成5份,其中一份作为验证集。然后经过5次(组)的测试,每次都更换不同的验证集。即得到5组模型的结果,取平均值作为最终结果。又称5折交叉验证。
    在这里插入图片描述
网格搜索
  1. 目的:对超参数进行搜索
  2. 使用网格搜索的原因:通常情况下,有很多参数是需要手动指定的(如k-近邻算法中的K值),这种叫超参数。但是手动过程繁杂,所以需要对模型预设几种超参数组合。每组超参数都采用交叉验证来进行评估。最后选出最优参数组合建立模型。
模型调优代码实现
  1. API: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_:每次交叉验证后的测试集准确率结果和训练集准确率结果
  2. 以k近邻算法为例的模型调优
import pandas as pd
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler

def knncls():

# 读取数据
    data = pd.read_csv(r"E:\data\facebook-v-predicting-check-ins\train.csv\train.csv")

# 缩小数据集范围
    data = data.query("x>1.0&x<1.25&y>1.0&y<1.25")

    # print(data.head(10))

# 把时间戳特征转化为天、小时、周,删除时间戳特征
    time_value = pd.to_datetime(data['time'],unit='s')
    # print(type(time_value))
    time_value = pd.DatetimeIndex(time_value)
    data['day'] = time_value.day
    data['hour'] = time_value.hour
    data['weekday'] = time_value.weekday
    data = data.drop(['time'],axis =1)
    print(data.head(10))

# 减少目标值个数,把签到数量小于3的目标位置删除
    place_count = data.groupby('place_id').count()
    tf = place_count[place_count.row_id>3].reset_index()
    data = data[data['place_id'].isin(tf.place_id)]

# 取出特征值和目标值
    y = data['place_id']
    x = data.drop(['place_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.fit_transform(x_test)

# knn算法流程
    knn = KNeighborsClassifier()


    # knn.fit(x_train,y_train)
    # y_predict = knn.predict(x_test)
    # print("预测目标签到位置为:",y_predict)
    # print(knn.score(x_test,y_test))


# 对knn的超参数进行优化
    # 参数备选范围
    param = {"n_neighbors": [3,5,7]}
    # 网格搜索
    gc = GridSearchCV(knn, param_grid=param, cv = 5)
    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_)

    return None



if __name__ == '__main__':
    knncls()

输出结果:

在测试集上准确率: 0.337936772046589
在交叉验证中的最好结果: 0.3361069506850835
最好的模型是: KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=None, n_neighbors=7, p=2,
           weights='uniform')
每个超参数每次交叉验证的结果为: {'mean_fit_time': array([0.10036383, 0.01190853, 0.01141105]), 'std_fit_time': array([0.16776234, 0.00257666, 0.00149117]), 'mean_score_time': array([0.25650139, 0.19496632, 0.20525126]), 'std_score_time': array([0.15538092, 0.01424587, 0.00708061]), 'param_n_neighbors': masked_array(data=[3, 5, 7],
             mask=[False, False, False],
       fill_value='?',
            dtype=object), 'params': [{'n_neighbors': 3}, {'n_neighbors': 5}, {'n_neighbors': 7}], 'split0_test_score': array([0.28536913, 0.32456376, 0.33583893]), 'split1_test_score': array([0.28361858, 0.31893507, 0.33441999]), 'split2_test_score': array([0.3024093 , 0.3303794 , 0.34561063]), 'split3_test_score': array([0.29421721, 0.32327221, 0.32665726]), 'split4_test_score': array([0.2969697 , 0.32871573, 0.33795094]), 'mean_test_score': array([0.29239474, 0.32512343, 0.33610695]), 'std_test_score': array([0.00711984, 0.00407093, 0.00607468]), 'rank_test_score': array([3, 2, 1]), 'split0_train_score': array([0.58033841, 0.52810796, 0.49531534]), 'split1_train_score': array([0.57709466, 0.52697616, 0.4928203 ]), 'split2_train_score': array([0.57810766, 0.5225444 , 0.48994173]), 'split3_train_score': array([0.57982323, 0.5222345 , 0.49240436]), 'split4_train_score': array([0.57807993, 0.52513391, 0.49031726]), 'mean_train_score': array([0.57868878, 0.52499938, 0.4921598 ]), 'std_train_score': array([0.00120481, 0.00233497, 0.00193744])}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值