【机器学习】KNN算法实战项目一:婚恋对象分类

2024-02-16 16:10

本文主要是介绍【机器学习】KNN算法实战项目一:婚恋对象分类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

KNN算法实战项目一:婚恋对象分类

  • 1 婚恋平台数据集KNN分析
    • 1.1 模块导入与数据加载
    • 1.2 数据EDA
    • 1.3 数据预处理
    • 1.4 模型创建与应用
    • 1.5 绘制决策边界

手动反爬虫: 原博地址 https://blog.csdn.net/lys_828/article/details/122588889

 知识梳理不易,请尊重劳动成果,文章仅发布在CSDN网站上,在其他网站看到该博文均属于未经作者授权的恶意爬取信息

KNN建模思想

已知样本集中每一数据与所属分类的对应关系,输入没有标签的新数据后,将新数据的每个特征与样本集中的数据对应的特征进行比较,提取样本集中特征最相似的数据(最近邻)的分类标签。 一般来说,我们只选择样本集中前k个最相似的数据,这就是k- 近邻算法中k的出处,通常k是不大于20的整数,最后,选择k个最相似的数据中出现次数最多的分类,作为新数据的分类。

KNN建模关键

(1)训练集、距离或相似性的度量、k的大小;

(2)被“多数投票”归为其邻居分类。
请添加图片描述

比如图中的绿点的分类,分别求解该点距离训练集中所有点的距离,然后根据给定的k值,圈出k个范围中最近的点,按照多数投票原则进行分类,这里就是两个蓝色一个红色,所以最终绿色点被划分为了蓝色。

KNN算法实现的四部曲

(1)决定K的数值 一般从1-20之间取值;

(2)在所有数据中计算与所需查询数据的距离;

(3) 把所有距离结果进行排序,找出最近的K个数据;

(4) 统计最近的K个数据的分类结果,按照投票统计结果,票数多的分类获胜。

K值的选择

(1)K取的比较大容易获得相对平稳的分界线;

(2)当k和数据量一样大时,KNN会把每组数据做成一个边界。

请添加图片描述

K值的选择如上图,如果较小,会分类很详细,就出现了过度拟合的现象,如果是给定的K值较大,会形成一个相对比较清晰的边界。

具体进行K值的选取,程序可以通过循环对比模型的得分,得分最高者即为K值最优,如下取K=1或者K=4得分最优,为了避免过拟合这时相对就会取到K=4。
请添加图片描述

1 婚恋平台数据集KNN分析

1.1 模块导入与数据加载

加载常用模块

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from sklearn.model_selection import train_test_split
import numpy as np%matplotlib inline

加载数据,注意原数据集中没有字段名称,而且数据之间分隔的形式并不是逗号,所以要指定sep参数,代码如下。

df1 = pd.read_csv('../data/datingTestSet.txt',sep='\t',header=None)
df1.head()

输出结果如下。
请添加图片描述

指定字段名称,分别为飞行里程、游戏时间比例、冷饮量 单位升、标签。其中标签字段中一共有三个分类:largeDoses对应’非常喜欢’、smallDoses对应’有点感觉’、didntLike对应’不喜欢’。

col1 = ['飞行里程','游戏时间比例','冷饮量 单位升','标签']
df1.columns=col1
df1.head()

输出结果如下。
请添加图片描述

可以将标签中的英文替换成为对应的中文信息,常用的操作就是利用字典方式,代码如下。

dict1={'largeDoses':'非常喜欢','smallDoses':'有点感觉','didntLike':'不喜欢'
}
df2=df1.copy()
df2['标签']=df2['标签'].map(dict1)
df1.head()
df1.head()

为了防止后续操作造成读入的原始数据损坏,建议操作在副本上进行,输出前后的对比结果如下。
请添加图片描述

1.2 数据EDA

数据准备好后,可以进行简单的数据EDA处理。由于除了标签字段外剩下的三个字段都是连续型数值数据,所以可以任意选择两个字段进行散点图的绘制,查看数据的分布,比如游戏时间比例与冷饮量 单位升之间的数据情况,代码如下。

plt.rcParams['font.sans-serif']=['SimHei']
plt.figure(figsize=(8,6))
sns.scatterplot(data=df1,x='游戏时间比例',y='冷饮量 单位升')

输出结果如下。
请添加图片描述

进一步可以通过控制标签字段的类别,来进行不同颜色的显示,只需要指定hue参数即可,代码及输出结果如下。
请添加图片描述
初步观察,发现对于不喜欢的类别,游戏时间比例是遍布了0-20的区间范围,但是有点喜欢和非常喜欢的类别中游戏时间比例有一个较为明显的分界线,可以尝试剔除一个分类后再看剩下的分类情况。

df2[df2['标签']!='不喜欢']
plt.figure(figsize=(8,6))
sns.scatterplot(data=df2[df2['标签']!='不喜欢'],x='游戏时间比例',y='冷饮量 单位升', hue='标签')

输出结果如下。去掉一个分类后,可以通过图形明显的发现游戏时间比例是有点感觉和非常喜欢之间的影响因素。
请添加图片描述

如果不喜欢这种x轴对比的方式,也可以调换xy轴的数据,只需要在指定x和y的参数时候调换字段名称即可,代码及输出结果如下。
请添加图片描述

除了探究上面两个字段外,还可以尝试游戏时间比例与飞行里程、冷饮量 单位升与飞行里程之间的关联,代码如下。

plt.figure(figsize=(8,6))
sns.scatterplot(data=df2,x='游戏时间比例',y='飞行里程', hue='标签')
plt.figure(figsize=(8,6))
sns.scatterplot(data=df2,x='冷饮量 单位升',y='飞行里程', hue='标签')

输出结果如下。
请添加图片描述
总共三个特征字段,两个关系分析一共有三个图,利用之前介绍过的pairplot也可以直接将关联图进行绘制,代码及输出结果如下。但是需要注意绘制图形时候字段数量不宜过多,不然各个子图形的显示会很小,不方便查看。
请添加图片描述

1.3 数据预处理

首先看一下数据的基本情况(这一步一般是在数据EDA第一步),通过info和describe方法进行查看,代码及输出结果如下。数据很干净,没有缺失值,不需要进行额外的处理。
请添加图片描述
预处理将数据进行划分,取出特征字段和标签字段,代码如下。

X = df2.drop(columns=['标签'])
y = df2['标签']
X 
y

输出结果如下。
请添加图片描述
由于KNN中判定的依据是距离,所以不同的字段之间的数值大小就是一个很重要的影响,比如这里飞行里程可以高达万级,但是冷饮量只有小数级别,故需要消除量级的影响,进行数据的标准化,可以采用之前大数据处理工具中的MinMaxScaler,StandardScaler,也可以自己手动书写。

from sklearn.preprocessing import MinMaxScaler,StandardScaler
def autoNorm(dataSet):minVals = dataSet.min(0)maxVals = dataSet.max(0)ranges = maxVals - minValsnormDataSet = np.zeros(np.shape(dataSet))m = dataSet.shape[0]normDataSet = dataSet - np.tile(minVals, (m,1))normDataSet = normDataSet/np.tile(ranges, (m,1))  return normDataSet, ranges, minVals
autoNorm(X)

输出结果如下。函数功能处理标准化外海可以输出变化的范围和最小值。(除此之外也可以根据需求进行自定义封装)
请添加图片描述
数据标准化后,进行训练集和测试集的切分。

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 0)
X_train.shape
X_test.shape
normDataSetX, ranges, minVals = autoNorm(X_train)
normDataSetX[:3]

输出结果如下。这里其实也可以先将X进行autoNorm赋值,然后再进行切分,这样就不用分别对训练集和测试集进行autoNorm了。
请添加图片描述

1.4 模型创建与应用

模型的创建与应用基本上和之前介绍的模型一致,代码解析如下。

#第一步:导入模型模块
from sklearn.neighbors import KNeighborsClassifier
#第二步:指定一个初始的K值
knn = KNeighborsClassifier(n_neighbors = 5)
#第三步:模型数据训练
knn.fit(normDataSetX, y_train)
#第四步:模型得分/预测
normDataSettestX, ranges, minVals = autoNorm(X_test)
knn.score(normDataSettestX, y_test)*100

输出结果如下。
请添加图片描述

1.5 绘制决策边界

重新取出特征字段的数据,重命名为df3,然后进行标准化,最后再合并特征数据。

df3=df2.iloc[:,:3]
normdf3,b,c= autoNorm(df3)
normdf3['标签']=df2['标签']
df2.head()
normdf3.head()

输出结果如下。
请添加图片描述
接着可以通过pairplot快速查看字段关联,为了核实消除量级后是否还会对数据分布有影响,代码及输出结果如下。对比y轴的刻度信息及图形样式,证明消除量级对数据分布没有影响。
请添加图片描述
以游戏时间比例和飞行里程为例进行决策边界的绘制,首先查看一下关系图,代码及输出结果如下。
请添加图片描述
需要注意封装的函数中需要用到c参数用于指定分类的颜色,这里c对应的就是标签中的分类信息,由于指定了是中文,导致无法正确识别颜色。因此可以进行标签值的对应,也是通过字典的方式,代码如下。

dict2 = {'不喜欢': 1,'有点感觉':2,'非常喜欢':3}
y_train2  = y_train.map(dict2)
y_train2
plot_date_knn(normDataSetX,y_train2,5,'uniform')

输出结果如下。
请添加图片描述
如果要解决负号问题,代码如下。

plt.rcParams['axes.unicode_minus']=False
plot_date_knn(normDataSetX,y_train2,5,'uniform')

输出结果中正常显示负号。
请添加图片描述
补充plot_date_knn函数全部代码,可以对比之前详细讲解决策边界的绘制过程。

def plot_date_knn(X, y, n_neighbors, weights):X_mat = X[['游戏时间比例', '飞行里程']].valuesy_mat = y.valuescmap_light = ListedColormap(['#FFAAAA', '#AAFFAA', '#AAAAFF'])cmap_bold = ListedColormap(['#FF0000', '#00FF00', '#0000FF'])clf = neighbors.KNeighborsClassifier(n_neighbors, weights=weights)clf.fit(X_mat, y_mat)mesh_step_size = .01  # step size in the meshplot_symbol_size = 50x_min, x_max = X_mat[:, 0].min() - 1, X_mat[:, 0].max() + 1y_min, y_max = X_mat[:, 1].min() - 1, X_mat[:, 1].max() + 1xx, yy = numpy.meshgrid(numpy.arange(x_min, x_max, mesh_step_size),numpy.arange(y_min, y_max, mesh_step_size))Z = clf.predict(numpy.c_[xx.ravel(), yy.ravel()])Z = Z.reshape(xx.shape)plt.figure()plt.rcParams['font.sans-serif']=['SimHei']plt.pcolormesh(xx, yy, Z, cmap=cmap_light)plt.scatter(X_mat[:, 0], X_mat[:, 1], s=plot_symbol_size, c=y, cmap=cmap_bold, edgecolor='black')plt.xlim(xx.min(), xx.max())plt.ylim(yy.min(), yy.max())patch0 = mpatches.Patch(color='#FF0000', label='不喜欢')patch1 = mpatches.Patch(color='#00FF00', label='有点感觉')patch2 = mpatches.Patch(color='#0000FF', label='非常喜欢')# patch3 = mpatches.Patch(color='#AFAFAF', label='lemon')plt.legend(handles=[patch0, patch1, patch2])plt.xlabel('游戏时间比例')plt.ylabel('飞行里程')plt.show()

这篇关于【机器学习】KNN算法实战项目一:婚恋对象分类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/715053

相关文章

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Pandas使用SQLite3实战

《Pandas使用SQLite3实战》本文主要介绍了Pandas使用SQLite3实战,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录1 环境准备2 从 SQLite3VlfrWQzgt 读取数据到 DataFrame基础用法:读

一文教你如何将maven项目转成web项目

《一文教你如何将maven项目转成web项目》在软件开发过程中,有时我们需要将一个普通的Maven项目转换为Web项目,以便能够部署到Web容器中运行,本文将详细介绍如何通过简单的步骤完成这一转换过程... 目录准备工作步骤一:修改​​pom.XML​​1.1 添加​​packaging​​标签1.2 添加

在java中如何将inputStream对象转换为File对象(不生成本地文件)

《在java中如何将inputStream对象转换为File对象(不生成本地文件)》:本文主要介绍在java中如何将inputStream对象转换为File对象(不生成本地文件),具有很好的参考价... 目录需求说明问题解决总结需求说明在后端中通过POI生成Excel文件流,将输出流(outputStre

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

tomcat多实例部署的项目实践

《tomcat多实例部署的项目实践》Tomcat多实例是指在一台设备上运行多个Tomcat服务,这些Tomcat相互独立,本文主要介绍了tomcat多实例部署的项目实践,具有一定的参考价值,感兴趣的可... 目录1.创建项目目录,测试文China编程件2js.创建实例的安装目录3.准备实例的配置文件4.编辑实例的

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

springboot集成Deepseek4j的项目实践

《springboot集成Deepseek4j的项目实践》本文主要介绍了springboot集成Deepseek4j的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录Deepseek4j快速开始Maven 依js赖基础配置基础使用示例1. 流式返回示例2. 进阶

SpringBoot项目启动报错"找不到或无法加载主类"的解决方法

《SpringBoot项目启动报错找不到或无法加载主类的解决方法》在使用IntelliJIDEA开发基于SpringBoot框架的Java程序时,可能会出现找不到或无法加载主类com.example.... 目录一、问题描述二、排查过程三、解决方案一、问题描述在使用 IntelliJ IDEA 开发基于