机器学习作业----KNN算法

一、k-近邻算法原理

为了判断未知样本的类别,以所有已知类别的样本作为参照,计算未知样本与所有已知样本的距离,从中选取与未知样本距离最近的K个已知样本,根据少数服从多数的投票法则,将未知样本与K个最邻近样本中所属类别占比较多的归为一类。

KNN的原理就是当预测一个新的值x的时候,根据它距离最近的K个点是什么类别来判断x属于哪个类别

二、点距离的计算

通常使用的距离函数有:欧氏距离、余弦距离、汉明距离、曼哈顿距离等,一般选欧氏距离作为距离度量,但是这是只适用于连续变量。

这里的p值是一个变量,

当p=1的时候就得到了 曼哈顿距离 ;

当p=2的时候就得到了欧氏距离。

三、k值的选择

如果 K 值比较小,就相当于未分类物体与它的邻居非常接近才行。这样产生的一个问题就是,如果邻居点是个噪声点,那么未分类物体的分类也会产生误差,这样 KNN 分类就会产生过拟合。
如果 K 值比较大,相当于距离过远的点也会对未知物体的分类产生影响,虽然这种情况的好处是鲁棒性强,但是不足也很明显,会产生欠拟合情况,也就是没有把未分类物体真正分类出来。

一般采用交叉验证的方式选取 K 值。交叉验证的思路就是,把样本集中的大部分样本作为训练集,剩余的小部分样本用于预测,来验证分类模型的准确性。

四、举例

此案例参考b站上一位博主的讲解~~~~~

预测打斗100次,接吻5次的电影是什么电影类型

代码实现

import operator
import numpy as np


#设计knn算法,利用欧拉公式计算最短距离
def knn(trainDate, testData, labels, k):
    # print(trainDate)
    # print(testData)
    # 将测试数据转为和训练集相同形状,tile函数的作用使矩阵行数和列上复制相应的份额,是倍数的关系
    testData=np.tile(testData,(trainDate.shape[0],1))

    # 利用欧拉公式计算距离
    tempData=(testData-trainDate)**2
    # 将计算的矩阵跨列相加
    tempData=tempData.sum(axis=1)
    tempData=tempData**0.5
    print(tempData)

    # 对距离进行从小到大排序,返回的是数组的索引值
    sortData=np.argsort(tempData)

    # 统计前k个的类型数量
    count={}
    for i in range(k):
        # 取出下标对应的类型
        vote=labels[sortData[i]]
        # 字典中 的get方法返回指定键的值,如果键不在字典中返回默认值0
        count[vote]=count.get(vote,0)+1
        # 按照字典中对象的第二个元素降序排列,返回list
        sortNewData=sorted(count.items(),key=operator.itemgetter(1),reverse=True)
    return sortNewData[0][0]


# 训练数据
trainData = np.array([
    [115, 6],
    [109, 8],
    [120, 9],
    [5, 78],
    [6, 60],
    [8, 69]
])
# 训练数据对用的标签
labels = np.array(['动作片', '动作片', '动作片', '爱情片', '爱情片', '爱情片'])
# 测试数据
testData = np.array([100, 5])
print(knn(trainData, testData, labels, 3))

五、预测毕业生的薪资等级

         自定义的数据集,可能会存在一些问题,有错误请多多包涵~~~~

professional:专业编号;gender:性别(1:男;0:女);age:年龄;socialSkill:社交能力;professionalSkill:专业能力;

isJob:薪资等级标签

csv中各个属性的直方图表示

 

import operator
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
from sklearn import metrics


def knn(trainDate, testData, labels, k):
    # print(trainDate)
    # print(testData)
    # 将测试数据转为和训练集相同形状,tile函数的作用使矩阵行数和列上复制相应的份额,是倍数的关系
    testData = np.tile(testData, (trainDate.shape[0], 1))

    # 利用欧拉公式计算距离
    tempData = (testData - trainDate) ** 2
    # 将计算的矩阵跨列相加
    tempData = tempData.sum(axis=1)
    tempData = tempData ** 0.5
    # print(tempData)

    # 对距离进行从小到大排序,返回的是数组的索引值
    sortData = np.argsort(tempData)

    # 统计前k个的类型数量
    count = {}
    for i in range(k):
        # 取出下标对应的类型
        vote = labels[sortData[i]]
        # 字典中 的get方法返回指定键的值,如果键不在字典中返回默认值0
        count[vote] = count.get(vote, 0) + 1
        # 按照字典中对象的第二个元素降序排列,返回list
        sortNewData = sorted(count.items(), key=operator.itemgetter(1), reverse=True)
    return sortNewData[0][0]


data = pd.read_csv('movie.csv')
# 将 Pandas 数据框转换为 Numpy 数组
X = data[['professional', 'gender', 'age', 'socialSkill', 'professionalSkill']].values
print(X[0:5])
# 标签
y = data['isJob'].values
print(y[0:5])
# 标准化数据,利用到了sklearn库函数标准化的方法
X = preprocessing.StandardScaler().fit_transform(X.astype(float))
print(X[0:5])
# 利用到了sklearn库函数标准化的方法,划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=4)
print('Train set:', X_train.shape, y_train.shape)
print('Test set:', X_test.shape, y_test.shape)
# 绘制直方图
data.hist(bins=100)
plt.show()
x_predict = []
for item in X_test:
    temp = knn(X_train, item, y_train, 1)
    x_predict.append(temp)
print(y_test)
print(x_predict)
print("Train set Accuracy: ", metrics.accuracy_score(y_test, x_predict))
# print("Test set Accuracy: ", metrics.accuracy_score(y_test, ))

 k=2

k=3

k=4

k=5

k=6

k的大小取值对精准率的影响不大,可能存在的原因是样本的自己制作的样本出现了一些不准确。在绘制样本的时候采用了excel的随机函数,比较不利于比较精确率。

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
作业一(Matlab) 假设x=(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20),y=( 2.94, 4.53, 5.96, 7.88, 9.02, 10.94, 12.14, 13.96, 14.74, 16.68, 17.79, 19.67, 21.20, 22.07, 23.75, 25.22, 27.17, 28.84, 29.84, 31.78).请写出拟合的直线方程,并画图(包括原数据点及拟合的直线),请打印出来。 请使用线性回归模型来拟合bodyfat数据。数据集介绍可阅读:https://www.mathworks.com/help/nnet/examples/body-fat-estimation.html 在matlab中,在命令行中输入[X,Y] = bodyfat_dataset; 即可获得一个拥有13个属性,252个样本的数据集。使用前200个样本来获得模型,并写出你所获得的模型。使用后52个样本做测试,汇报你所获得的泛化误差。 编程实现对数回归,并给出教材89页上的西瓜数据集3.0上的结果。要求采用4折交叉验证法来评估结果。因为此处一共17个样本,你可以去掉最后一个样本,也可以用所有数据,然后测试用5个样本。在汇报结果时,请说明你的选择。请在二维图上画出你的结果(用两种不同颜色或者形状来标注类别),同时打印出完整的代码。 作业二 采用信息增益准则,基于表4.2中编号为1、2、3、6、7、9、10、14、15、16、17的11个样本的色泽、根蒂、敲声、文理属性构建决策树。(本次作业可以用笔算,鼓励编程实现,但都需要列出主要步骤,其中log2(3)=1.585,log2(5)=2.322,log2(6)=2.585,log2(7)=2.807,log2(9)=3.17,log2(10)=3.322,log2(11)=3.459) 用表4.2中编号为4、5、8、11、12、13的样本做测试集,对上题的训练数据采用预剪枝策略构建决策树,并汇报验证集精度。 用表4.2中编号为4、5、8、11、12、13的样本做测试集,对题1所构建的决策树进行后剪枝,并汇报验证集精度。 作业三(Matlab) 试编程实现累积BP算法,在西瓜数据集2.0上(用训练数据)训练一个单隐层网络,用验证集计算出均方误差。要自己实现,不能直接调用现成的库函数。 作业四 下载并安装libsvm,http://www.csie.ntu.edu.tw/~cjlin/libsvm/ ,在西瓜数据集3.0a上分别用线性核训练一个SVM。用正类1-6和负类9-14作为训练集,其余作为测试集。C取不同的值,其它参数设为默认值。作出测试正确率随C取值变化的图,C=[1 100 10000 10^6 10^8]。 换成高斯核(宽度设为1),重复上题的步骤。 作业五 以西瓜数据集2.0(见教材76页表4.1)中样本1--16为训练集训练一个朴素贝叶斯分类器,对测试样本17进行分类。请写出详细的计算过程。 假设x_k是一个班上学生的分数,对应的分数及其分布是 x_1=30, P1=0.5,一共有14个学生; x_2=18, P2=mu,有6个学生; x_3=20, P3=2mu,有9个学生; x_4=23, P4=0.5-3mu,有10个学生; 通过最大对数似然法求出mu的值。 作业六(Python) 1 使用PCA对Yale人脸数据集进行降维,并分别观察前20、前100个特征向量所对应的图像。请随机选取3张照片来对比效果。数据集http://vision.ucsd.edu/content/yale-face-database
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cpp_1211

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值