机器学习 之k-近邻算法实战案例学习

机器学习之k-近邻算法案例实战

本博客讲解knn算法的实际案例运用,采用jupyter note逐步讲解,及后面用python进行封装,偏于读者对knn算法的整体了解。
本博客涉及两个小案例。
1、电影类别的分类
2、约会网站的分析

1、电影类别的分类

1.1 电影数据如图1

图1
由图1知:
判断一个电影类型,我们用两个指标,打斗镜头和接吻镜头,通过这两个指标所占的数量来判断电影类型是动作片还是爱情片。
新电影的数据已知,我们采用knn近邻算法能够解决这个问题。

1.2 实现knn近邻算法(jupyter notebook)
#导入包
import pandas as pd
#1、导入数据
rowdata = {'电影名称':['无问西东','后来的我们','前任3','红海行动','唐人街探案','战狼2'],
           '打斗镜头':[1,5,12,108,112,115],
           '接吻镜头':[101,89,97,5,9,8],
           '电影类型':['爱情片','爱情片','爱情片','动作片','动作片','动作片']}

#将数据转换成二维表格形式
movie_data = pd.DataFrame(rowdata)
movie_data 

如图2:
图2

#2、计算距离
#新电影数据
new_data = [24,67]
#计算距离
dist = list((((movie_data.iloc[:6,1:3] - new_data)**2).sum(1))**0.5)
dist

#3、将距离升序排序,然后选取距离最小的k个点
#将距离与标签对应
dist_label = pd.DataFrame({'dist':dist,'label':(movie_data.iloc[:6,1:3])})
dist_label
#升序
dist_label.sort_values(by = 'dist')
#4、确定前k个点所在类别的出现频率
k=4
dr = dist_label.sort_values(by = 'dist')[:k]
dr

如图3:
图3

#5、确定前k个点所在类别的出现频率
re = dr.loc[:,'label'].value_counts()
re
#识别结果
result = []
result.append(re.index[0])
result
1.3 封装成函数
import pandas as pd

class Moviesort():
    #1、构建数据
    rowdata = {'电影名称':['无问西东','后来的我们','前任3','红海行动','唐人街探案','战狼2'],
                     '打斗镜头':[1,5,12,108,112,115],
                     '接吻镜头':[101,89,97,5,9,8],
                     '电影类型':['爱情片','爱情片','爱情片','动作片','动作片','动作片']}

    movie_data = pd.DataFrame(rowdata)
    #1、计算距离
    def distance(self,new_data):
        dist = list((((movie_data.iloc[:,1:3] - new_data)**2).sum(1))**0.5)
        return dist
    
    #2、找出前k个距离最近的值
    def dist_label(self,k):
        result = []
        #将距离与标签对应
        d_l = pd.DataFrame({'dist':dist,'label':(movie_data.iloc[:,3])})
        #对距离值做升序
        d_v = d_l.sort_values(by='dist')[:k]
        #对前k个标签进行统计
        label_num = d_v.loc[:,'label'].value_counts()
        re = label_num.index[0]
        result.append(re)
        return result
    
def main():
    
    m = Moviesort()
    #new_data=[24,67]
    m.distance([24,67])
    print(dist)
    #k=4
    m.dist_label(4)
    print(result)
        
    
if __name__ == '__main__':
    main()
    

2、约会网站数据分析

2.1 加载约会网站数据
datingTest = pd.read_table('datingTestSet.txt',header=None)
datingTest.head()
2.2 分析数据
%matplotlib inline 
import matplotlib as mpl 
import matplotlib.pyplot as plt

#将不同标签用颜色区分
colors = []
for i in range(datingTest.shape[0]):
    m = datingTest.iloc[i,-1]
    if m == 'didntLike':
        colors.append('black')
    elif m == 'smallDoses':
        colors.append('orange')
    elif m == 'largeDoses':
        colors.append('red')

#绘制两两特征之间的散点图
plt.rcParams['font.sans-serif'] = ['Simhei'] #图中字体设置为黑体
pl = plt.figure(figsize=(12,8))
fig1 = pl.add_subplot(221) #x,y,标签1
plt.scatter(datingTest.iloc[:,1],datingTest.iloc[:,2],marker='.',c=colors)
plt.xlabel('玩游戏视频所占时间比') 
plt.ylabel('每周消费冰激凌公升数')


fig2 = pl.add_subplot(222) #x,y,标签2
plt.scatter(datingTest.iloc[:,0],datingTest.iloc[:,1],marker='.',c=colors)
plt.xlabel('每年飞行常客里程') 
plt.ylabel('玩游戏视频所占时间比')


fig3 = pl.add_subplot(223) #x,y,标签3
plt.scatter(datingTest.iloc[:,0],datingTest.iloc[:,2],marker='.',c=colors)
plt.xlabel('每年飞行常客里程') 
plt.ylabel('每周消费冰激凌公升数')

plt.show()
    


3、数据归一化
'''
函数功能:归一化
参数说明:dataset:原始数据集
返回:0-1标准化之后的数据集
'''

def minmax(dataset):
    minDf = dataset.min()
    maxDf = dataset.max()
    normset = (dataset - minDf) / (maxDf - minDf)
    return normset

#将数据代入函数,进行归一化处理
datingT = pd.concat([minmax(datingTest.iloc[:,:3]),datingTest.iloc[:,3]],axis=1)
datingT
4、划分训练集与测试集
#90%的训练集,10%的测试集


'''
函数功能:切分训练集与测试集
参数说明:dataset:原始数据集
          rate:训练集所占比例
返回:切分好的训练集和测试集
'''
def randsplit(dataset,rate=0.9):
    n = dataset.shape[0] #行数
    m = int(n*rate) #训练集比例
    train = dataset.iloc[:m,:]
    test = dataset.iloc[m:,:]
    test.index = range(test.shape[0])
    return train,test

train,test = randsplit(datingT)
train
test


5、测试代码
'''
函数功能:k-近邻算法分类器
参数说明:
          train:训练集、
          test:测试集
          k:k-近邻参数,即选择距离最小的k个点
返回:预测好分类的测试集
'''
def datingclass(train,test,k):
    n = train.shape[1] - 1
    m = test.shape[0]
    result = []
    #k-近邻算法
    for i in range(m):
        #1、计算距离
        dist = list((((train.iloc[:,:n] - test.iloc[i,:n])**2).sum(1))**0.5)
        #2、取前k个距离最近值
        #test加标签
        d_l = pd.DataFrame({'dist':dist,'label':(train.iloc[:,n])})
        #对距离排序取前k个值
        dist_value = d_l.sort_values(by='dist')[:k]
        #统计类别数量
        label_num = dist_value.loc[:,'label'].value_counts()
        result.append(label_num.index[0]) #概率最大的标签在最前面
    
    result = pd.Series(result)
    test['predict'] = result
    acc = (test.iloc[:,-1] == test.iloc[:,-2]).mean()
    print(f'模型预测准确率为{acc}')
    print(dist_value)
    return test
2.3 用python函数封装
import pandas as pd
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt


class Data_knn:
    #1、数据准备
    dataloader = pd.read_table('datingTestSet.txt',header = None)
    datingTest = dataloader
    
    #2、数据归一化
    def data_norm(self,dataset):
        data = dataset.iloc[:,:3]
        minDf = data.min()
        maxDf = data.max()
        normset = (data - minDf) / (maxDf - minDf)
        return normset
    
    
    
    #2、分析数据
    def analyze_data(self,dataset):
        #把不同标签用颜色区分
        colors = []
        for i in range(datingTest.shape[0]):
            m = datingTest.iloc[i,-1]
            if m == 'didntLike':
                colors.append('black')
            elif m == 'smallDoses':
                colors.append('orange')
            elif m == 'largeDoses':
                colors.append('red')
                

        
        plt.rcParams['font.sans-serif'] = ['simhei'] #图中字体为黑体
        pl = plt.figure(figsize=(12,8))
        fig1 = pl.add_subplot(221)
        plt.scatter(datingTest.iloc[:,1],datingTest.iloc[:,2],marker='.',c=colors)
        plt.xlabel('玩游戏视频所占时间比')
        plt.ylabel('每周消费冰淇淋公升数')
        
        fig2 = pl.add_subplot(222)
        plt.scatter(datingTest.iloc[:,0],datingTest.iloc[:,1],marker='.',c=colors)
        plt.xlabel('每年飞行常客里程')
        plt.ylabel('玩游戏视频所占时间比')
        
        fig3 = pl.add_subplot(223)
        plt.scatter(datingTest.iloc[:,0],datingTest.iloc[:,2],marker='.',c=colors)
        plt.xlabel('每年飞行常客里程')
        plt.ylabel('每周消费冰淇淋公升数')
        
        plt.show()
        
    #训练   
    def test_knn(self,dataset,k,rate=0.9):
        #划分数据集
        n = dataset.shape[0]
        m = int(n*rate)
        train = dataset.iloc[:m,:]
        test = dataset.iloc[m:,:]
        #将test数据集索引从0开始
        test.index = range(test.shape[0])
        #k-近邻
        #计算距离
        a = train.shape[1] - 1
        b = test.shape[0]
        
        result = []
        for i in range(b):
            
            dist = list((((train.iloc[:,:a] - test.iloc[i,:a])**2).sum(1))**0.5)
            #给距离加标签
            d_l = pd.DataFrame({'dist':dist,'label':(train.iloc[:,-1])})
            #提取前面k个最小的距离
            d_v = d_l.sort_values(by='dist')[:k]
            #统计前k个标签的概率
            re = d_v.loc[:,'label'].value_counts()
            result.append(re.index[0])
        result = pd.Series(result)
        test['predict'] = result
        acc = (test.iloc[:,-1] == test.iloc[:,-2]).mean()
        print(f'模型预测准确率为{acc}')
        return test       

d = Data_knn()
test = d.test_knn(datingTest,k=5)
test
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值