类别型特征
#机器学习 #深度学习 #基础知识 #特征工程 #数据编码
背景
在现实生活中,我们面对的数据类型有很多,其中有的数据天然为数值类型具备数值意义,那么可以很自然地和算法结合,但是大部分数据他没有天然的数值意义,那么将他们送入到算法前,就需要对数据进行编码处理,将其转换为数值类型,才可以送入算法进行运算.
问题
处理一个这样算法问题时,首先我们需要确认所处理的数据是什么类型的,是否可以直接输入模型,如果不能,那么我们需要根据数据本身的特点,然后结合算法的适配的格式,去对数据进行编码处理.因此,我们需要依次思考以下的几个问题:
- 常见的类别数据有哪些形式?其中有哪些是需要进行编码的?
- 哪些算法能接收未经编码的类别型特征?哪些算法不能?
- 常见的编码类型及其优缺点?如何选择适合的编码方式?
解决方案
常见的类别特征有哪些?其中有哪些是需要进行编码的?
类别型特征是指在数据集中表示某种类别或属性的特征。它包含有限个离散的取值,通常用于描述无序的分类或标签信息。类别型特征没有固定的数值间隔和数值运算意义,只表示不同类别之间的区别和关系。
例如,性别、颜色、地区、职业、喜好程度、股票种类、专业等都可以是类别型特征。性别可以有两个取值:男和女;颜色可以有多个取值:红、蓝、绿等;地区可以有多个取值:东、南、西、北等;职业可以有多个取值:医生、教师、工程师等;问卷调查中,对一件事的喜好程度分为厌恶、无感、较喜欢、喜欢、特别喜欢等;股票可以分为煤炭,光伏,消费,白酒,医疗等等不同的板块;高考报志愿时,专业可以分为计算机科学,基础物理学,临床医学,兽医学,法律,文学等等.
总结来看,这些类别特征按照是否有序可以分为: 有序类别特征(Ordinal Categorical Features)是指类别之间存在自然顺序或等级关系的特征。这类特征的值可以进行排序,但不能直接进行数值运算;无序类别特征(Nominal Categorical Features)是指类别之间没有自然顺序或等级关系的特征。这类特征的值只是表示不同的类别,不存在排序关系。要是按照类别的数量来来分:高基类类别特征,具有大量唯一值的类别,特征类别总数很大;低基类类别特征,具有少量唯一值的类别,特征类别总数较少.
关于哪些类别特征需要编码,这个问题其实需要结合所采用的算法统筹考虑才有实际意义.但是,单从类别特征的分类上来考虑,可以划分为四种类型,它们的编码难点可以总结为下:
有序 | 无序 | |
低基类 | 保留类别顺序关系,保证类别均衡 | 保证类别间独立,保证类别均衡 |
高基类 | 保留类别关系,防止过拟合,解决稀疏性 | 保证类别间独立,解决稀疏性 |
哪些算法能接收未经编码的类别特征?哪些算法不能?
首先,没有经过编码的数据大多数为字符串类型.不同的算法所接受的数据格式是不同的,所以根据具体算法接收的数据格式来看.一般来说,只有能够直接依据类别划分就能进行运行的算法可以不用进行编码,决策树类算法(决策树,随机森林),规则基础算法(C5.0)以及基于统计概率的部分贝叶斯分类算法,其余的算法都需要对类别型特征进行编码处理后才能让算法正常运行.
常见的编码类型及其优缺点?如何选择适合的编码方式?
标签编码
不适用于高基类类别特征,并且编码后的自然数对于回归任务来说是线性不可分的,即自然数之间的关系不能代表编码前的类别关系.
哈稀编码
将类别特征通过哈希函数映射到固定数量的哈希桶中。这种方法在类别数量非常多时可以减小维度,但可能引入哈希冲突。
独热编码
独热编码(One-Hot Encoding),又称一位有效编码,其方法是使用N位状态寄存器来对N个状态进行编码,每个状态都有它独立的寄存器位,并且在任意时候,其中只有一位有效。这个方法能很好的保证编码后,各个类别特征的独立性,但是面对高基类类型特征时,会比较稀疏从而浪费资源.
计数编码
计数编码(Count Encoding,也称频率编码)的过程,可以按照以下步骤进行:
- 原始类别数据:列出原始的类别数据。
- 计算类别频数:计算每个类别在数据集中出现的频数。
- 替换类别值:用类别的频数替换原始的类别值。
假设我们有一个类别特征 "Color",它有以下类别值:红色、绿色、蓝色、黄色、绿色、红色、蓝色。我们将计算这些颜色频数得:红色:2,绿色:2,蓝色:2,黄色:1。这种编码方式的问题显而易见,编码只关注了类别在数据集中出现的频次,但是忽略了类别本身的意义.所以,这种方式可能只适用于模型不关心类别意义,而关注类别统计属性的模型中.
直方图编码
实际上直方图编码,也是基于统计的编码,只不过它统计的不是单纯类别样本出现的次数,而是某一种特征在不同类别中的出现频次.这样我们通过先验的统计这些每个类别中这些特征的频次,然后观察样本中表现出的特征,来预测这个样本的类别.直方图编码能清晰看出特征下不同类别对不同预测标签的贡献度,缺点在于:使用了标签数据,若训练集和测试集的类别特征分布不一致,那么编码结果容易引发过拟合。此外,直方图编码出的特征数量是分类标签的类别数量,若标签类别很多,可能会给训练带来空间和时间上的负担。
WOE编码
权重证据编码(Weight of Evidence Encoding, WOE)的过程,我们可以按照以下步骤进行:
- 原始类别数据:列出原始的类别数据和目标变量。
- 计算类别的WOE值:计算每个类别的WOE值。
- 替换类别值:用类别的WOE值替换原始的类别值。
假设我们有一个类别特征 "Color",它有以下类别值:红色、绿色、蓝色、黄色,并且有一个二进制目标变量 "Target"。
权重证据(WOE)的计算公式为:
其中,"Good" 和 "Bad" 通常是正类和负类的计数。
我们需要计算每个类别的Good和Bad的分布:
- 红色:Good = 1,Bad = 1
- 绿色:Good = 1,Bad = 1
- 蓝色:Good = 1,Bad = 1
- 黄色:Good = 0,Bad = 1
总的Good和Bad数量:
- Total Good = 3
- Total Bad = 4
计算WOE值:
- 红色:
- 绿色:
- 蓝色:
- 黄色:
(注意:在实际应用中我们会处理这种情况)
透过公式,我们可以把WOE理解成:每个分组内坏客户分布相对于优质客户分布之间的差异性。
WOE存在几个问题:
- 分母可能为0.
- 没有考虑不同类别数量的大小带来的影响,可能某类数量多,但最后计算出的WOE跟某样本数量少的类别的WOE一样。
- 只针对二分类问题。
- 训练集和测试集可能存在WOE编码差异(通病)。
对于问题1,可加入regularization(默认值为1)。
目标编码
亦称均值编码(mean encoding)、似然编码(likelihood encoding)、效应编码(impact encoding),是一种能够对高基数(high cardinality)自变量进行编码的方法 (Micci-Barreca 2001) 。如果某一个特征是定性的(categorical),而这个特征的可能值非常多(高基数),那么目标编码(Target encoding)是一种高效的编码方式。在实际应用中,这类特征工程能极大提升模型的性能。
模型编码
其实模型编码思想很简单,即用神经网络来将输入的数据映射到一个易于算法进行的空间中.这也是很多预训练模型能够有利于实际任务的原因.但是,其中的优点与缺点也十分明显,优点是利用深度学将远特征映射到更有剖利于算法施行的空间中,缺点是需要大量数据做预训练,以及使用深度学习模型会可能有较大的资源消耗.
代码实践
标签编码
Scikit-learn中的LabelEncoder是用来对分类型特征值进行编码,即对不连续的数值或文本进行编码。其中包含以下常用方法:
- fit(y) :fit可看做一本空字典,y可看作要塞到字典中的词。
- fit_transform(y):相当于先进行fit再进行transform,即把y塞到字典中去以后再进行transform得到索引值。
- inverse_transform(y):根据索引值y获得原始数据。
- transform(y) :将y转变成索引值。
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
city_list = ["red", "green", "blue", "red"]
le.fit(city_list)
print(le.classes_) # 输出为:['blue' 'green' 'red']
city_list_le = le.transform(city_list) # 进行Encode
print(city_list_le) # 输出为:[2 1 0 2]
city_list_new = le.inverse_transform(city_list_le) # 进行decode
print(city_list_new) # 输出为:['red' 'green' 'blue' 'red']
哈稀编码
可以自由的定义hash函数,原则上不要产生过多碰撞就行,其中依据什么来hash可以结合具体情况选择,以便编码后的特征有利于算法的进行
import pandas as pd
import numpy as np# 原始数据
data = {'类别特征': ['Apple', 'Banana', 'Orange', 'Banana', 'Apple', 'Orange', 'Grape', 'Apple']
}
df = pd.DataFrame(data)# 选择哈希桶数量
num_buckets = 4# 定义哈希编码函数
def hash_encode(value, num_buckets):return hash(value) % num_buckets# 应用哈希编码函数
df['哈希值'] = df['类别特征'].apply(lambda x: hash_encode(x, num_buckets))# 独热编码哈希值
hash_encoded = pd.get_dummies(df['哈希值'], prefix='哈希桶')# 将哈希编码结果合并到原始数据中
result_df = pd.concat([df, hash_encoded], axis=1)# 打印结果
print(result_df)
独热编码
LabelBinarizer:将对应的数据转换为二进制型,类似于onehot编码,这里有几点不同:
- 可以处理数值型和类别型数据
- 输入必须为1D数组
- 可以自己设置正类和父类的表示方式
from sklearn.preprocessing import LabelBinarizerlb = LabelBinarizer()city_list = ["red", "blue", "green", "blue"]lb.fit(city_list)
print(lb.classes_) # 输出为:['blue' 'green' 'red']city_list_le = lb.transform(city_list) # 进行Encode
print(city_list_le)
# 输出为:
# [[0 0 1]
# [1 0 0]
# [0 1 0]
# [1 0 0]]
计数编码
import pandas as pd# 原始数据
data = {'类别特征': ['Apple', 'Banana', 'Orange', 'Banana', 'Apple', 'Orange', 'Grape', 'Apple']
}
df = pd.DataFrame(data)# 计算每个类别的频数
frequency_encoding = df['类别特征'].value_counts()# 应用频数编码
df['频数编码'] = df['类别特征'].map(frequency_encoding)# 打印结果
print(df)
直方图编码
计数编码是统计单纯特征数量,直方图编码是统计特征在不同类别中的分布.
import pandas as pd# 原始数据
data = {'类别特征': ['A', 'A', 'B', 'B', 'A', 'A', 'B'],'目标变量': [0, 1, 0, 1, 2, 2, 2]
}
df = pd.DataFrame(data)# 计算每个类别特征在目标变量各个取值上的分布
histogram_encoding = df.groupby('类别特征')['目标变量'].value_counts(normalize=True).unstack(fill_value=0)# 为了便于合并,将列名转换为字符串
histogram_encoding.columns = [f'目标变量_{col}' for col in histogram_encoding.columns]# 合并编码结果到原始数据
df = df.join(histogram_encoding, on='类别特征')# 打印结果
print(df)
WOE编码
WOE值的计算公式为:
WOE=ln(正样本比例负样本比例)WOE=ln(负样本比例正样本比例)
其中:
- 正样本比例(Positive Rate):该类别在正样本中的占比。
- 负样本比例(Negative Rate):该类别在负样本中的占比。
import pandas as pd
import numpy as np# 原始数据
data = {'类别特征': ['A', 'A', 'B', 'B', 'A', 'A', 'B', 'A'],'目标变量': [0, 1, 0, 1, 1, 0, 1, 0]
}
df = pd.DataFrame(data)# 计算每个类别的正负样本数量
total_positive = df['目标变量'].sum()
total_negative = len(df) - total_positive# 计算每个类别的正负样本数量
positive_count = df[df['目标变量'] == 1].groupby('类别特征').size()
negative_count = df[df['目标变量'] == 0].groupby('类别特征').size()# 计算每个类别的正负样本比例
positive_ratio = positive_count / total_positive
negative_ratio = negative_count / total_negative# 填充缺失值为0
positive_ratio = positive_ratio.fillna(0)
negative_ratio = negative_ratio.fillna(0)# 计算WOE值
woe = np.log(positive_ratio / negative_ratio)# 打印每个类别的WOE值
print(woe)# 应用WOE编码
df['WOE编码'] = df['类别特征'].map(woe)# 打印结果
print(df)
目标编码
根据属性与类别的分布统计,用似然函数进行编码
import pandas as pd# 原始数据
data = {'类别特征': ['A', 'B', 'A', 'B', 'A', 'C', 'B', 'C', 'A', 'B'],'目标变量': [1, 0, 1, 1, 0, 0, 1, 0, 1, 1]
}
df = pd.DataFrame(data)# 计算每个类别的目标变量均值
target_mean = df.groupby('类别特征')['目标变量'].mean()# 打印每个类别的目标变量均值
print("目标变量均值:\n", target_mean)# 应用目标编码
df['目标编码'] = df['类别特征'].map(target_mean)# 打印结果
print("\n目标编码结果:\n", df)
模型编码
在各个领域中的backbone预训练模型,以及当下在大模型领域广泛运用的CLIP.
总结
处理类别型编码时,需要综合考虑数据本身的特性:数据量,类别量,样本的分布特性,样本属性重要程度;算法的适应性:输入的数据的型式,算法效率,算法进度;实际处理问题的需要和目标.总之,针对这一类类别型特征的编码,其目的是将这类结构化的数据映射到一个易于算法处理的空间中.
参考链接
https://zhuanlan.zhihu.com/p/349592092
https://zhuanlan.zhihu.com/p/480609142
相关文章:
类别型特征
#机器学习 #深度学习 #基础知识 #特征工程 #数据编码 背景 在现实生活中,我们面对的数据类型有很多,其中有的数据天然为数值类型具备数值意义,那么可以很自然地和算法结合,但是大部分数据他没有天然的数值意义,那么将他们送入到算法前,就需要对数据进行编码处理,将其转换为数…...

java医院管理系统源码(springboot+vue+mysql)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的医院管理系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 医院管理系统的主要使用者分…...
vue2 面试题
一、.vue的性能优化怎么做? 1.编码优化: 不要把所有的数据都放在data中;v-for时给每个元素绑定事件用事件代理;keep-alive缓存组件;尽可能拆分组件,提高复用性、维护性;key值要保证唯一&#…...

【JavaEE精炼宝库】多线程(3)线程安全 | synchronized
目录 一、线程安全 1.1 经典线程不安全案例: 1.2 线程安全的概念: 1.3 线程不安全的原因: 1.3.1 案例刨析: 1.3.2 线程不安全的名词解释: 1.3.3 Java 内存模型 (JMM): 1.3.4 解决线程不安全问题: 二…...

el-table-column两种方法处理特殊字段,插槽和函数
问题:后端返回的字段为数字 解决办法: {{ row[item.prop] 1 ? "启用" : "禁用" }} {{ row[item.prop] }} 最终果: 另外:如果多种状态时可用函数 {{ getStatus(row[item.prop]) }} {{ row[item.prop…...

huggingface笔记: accelerate estimate-memory 命令
探索可用于某一机器的潜在模型时,了解模型的大小以及它是否适合当前显卡的内存是一个非常复杂的问题。为了缓解这个问题,Accelerate 提供了一个 命令行命令 accelerate estimate-memory。 accelerate estimate-memory {MODEL_NAME} --library_name {LIBR…...

李飞飞亲自撰文:大模型不存在主观感觉能力,多少亿参数都不行
近日,李飞飞连同斯坦福大学以人为本人工智能研究所 HAI 联合主任 John Etchemendy 教授联合撰写了一篇文章,文章对 AI 到底有没有感觉能力(sentient)进行了深入探讨。 「空间智能是人工智能拼图中的关键一环。」知名「AI 教母」李…...
超级好用的C++实用库之套接字
💡 需要该C实用库源码的大佬们,可搜索微信公众号“希望睿智”。添加关注后,输入消息“超级好用的C实用库”,即可获得源码的下载链接。 概述 C中的Socket编程是实现网络通信的基础,允许程序通过网络与其他程序交换数据。…...

C++ | Leetcode C++题解之第108题将有序数组转换为二叉搜索树
题目: 题解: class Solution { public:TreeNode* sortedArrayToBST(vector<int>& nums) {return helper(nums, 0, nums.size() - 1);}TreeNode* helper(vector<int>& nums, int left, int right) {if (left > right) {return nu…...
5月27日,每日信息差
第一、韩国宇宙航空厅于 5 月 27 日正式成立,旨在推动以民间为主的太空产业生态圈发展,助力韩国成为航天强国。首任厅长尹宁彬表示,该机构将在庆尚南道泗川市的临时大楼开展相关工作。 第二、京东集团宣布,自2024年7月1日起&…...

echart扩展插件词云echarts-wordcloud
echart扩展插件词云echarts-wordcloud 一、效果图二、主要代码 一、效果图 二、主要代码 // 安装插件 npm i echarts-wordcloud -Simport * as echarts from echarts; import echarts-wordcloud; //下载插件echarts-wordcloud import wordcloudBg from /components/wordcloudB…...
解决无法直接抓取链接地址
当我们在爬取一些文章列表的时候,可能无法从接口或者html界面上获取到文章的详细列表 这个时候我们可以通过模拟点击且重写window.open方法,将跳转的地址捕获,并且放到html中去。 这样我们就可以获取到某个文章的详细地址了 // 保存原始的 …...

java面对对象编程-多态
介绍 方法的多态 多态是在继承,重载,重写的基础上实现的 我们可以看看这个代码 package b;public class main_ {public static void main(String[] args) { // graduate granew graduate(); // gra.cry();//这个时候,子类的cry方法就重写…...

【Sql Server】随机查询一条表记录,并重重温回顾下自定义函数的封装和使用
大家好,我是全栈小5,欢迎来到《小5讲堂》。 这是《Sql Server》系列文章,每篇文章将以博主理解的角度展开讲解。 温馨提示:博主能力有限,理解水平有限,若有不对之处望指正! 目录 前言随机查询语…...

基于C#开发web网页管理系统模板流程-主界面管理员录入和编辑功能完善
前言 紧接上篇->基于C#开发web网页管理系统模板流程-登录界面和主界面_c#的网页编程-CSDN博客 已经完成了登录界面和主界面,本篇将完善主界面的管理员录入和编辑功能,事实上管理员录入和编辑的设计套路适用于所有静态表的录入和编辑 首先还是介绍一下…...

K8s证书过期处理
问题描述 本地有一个1master2worker的k8s集群,今天启动VMware虚拟机之后发现api-server没有起来,docker一直退出,这个集群是使用kubeadm安装的。 于是kubectl logs查看了日志,发现证书过期了 解决方案: 查看证书 #…...

刷题之路径总和Ⅲ(leetcode)
路径总和Ⅲ 这题和和《为K的数组》思路一致,也是用前缀表。 代码调试过,所以还加一部分用前序遍历数组和中序遍历数组构造二叉树的代码。 #include<vector> #include<unordered_map> #include<iostream> using namespace std; //Def…...
MongoDB 原子操作:确保数据一致性和完整性的关键
在 MongoDB 中,原子操作是指可以一次性、不可分割地执行的数据库操作。这些操作能够保证在多个并发操作中不会出现数据不一致或者丢失的情况,确保数据库的数据完整性和一致性。 基本语法 MongoDB 的原子操作通常与更新操作相关,其基本语法如…...
2024上半年软考高级系统架构设计师回顾
本博客地址:https://security.blog.csdn.net/article/details/139238685 2024年上半年软考在5月25-26日举行,趁着时间刚过去记忆还在,简单写一点总结。 关于考试形式:上机考试(以后也都是机考)࿰…...
SQL注入绕过技术深度解析与防御策略
引言 在Web安全领域,SQL注入攻击一直是一个棘手的问题。攻击者通过SQL注入手段获取敏感数据、执行恶意操作,甚至完全控制系统。尽管许多防御措施已被广泛采用,但攻击者仍不断开发新的绕过技术。本文将深度解析SQL注入的绕过技术,…...
SpringCloud——Nacos
1、核心功能: 服务注册与发现: 服务实例可动态注入到Nacos中,消费者通过服务名发现可用实例。 // 启用EnableDiscoveryClient注解启用Nacos SpringBootApplication EnableDiscoveryClient public class UserServiceApplication {public st…...

《架构即未来》笔记
思维导图 第一部分:可扩展性组织的人员配置 第二部分:构建可扩展的过程 第三部分:可扩展的架构方案 第四部分:其他的问题和挑战 资料 问软件工程研究所: https://www.sei.cmu.edu/ AKF公司博客: http://www.akfpart…...

基于规则的自然语言处理
基于规则的自然语言处理 规则方法形态还原(针对英语、德语、法语等)中文分词切分歧义分词方法歧义字段消歧方法分词带来的问题 词性标注命名实体分类机器翻译规则方法的问题 规则方法 以规则形式表示语言知识,强调人对语言知识的理性整理&am…...
SpringBoot3中使用虚拟线程的详细过程
在 Spring Boot 3 中使用 Java 21 的虚拟线程(Virtual Threads)可以显著提升 I/O 密集型应用的并发能力。以下是详细实现步骤: 1. 环境准备 JDK 21:确保安装 JDK 21 或更高版本Spring Boot 3.2:最低要求(p…...

面试心得 --- 车载诊断测试常见的一些面试问题
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...
当前市场环境下,软件行业的突围之道:技术演进与商业模式重构
一、行业背景:软件行业进入结构性调整期 2024年至今,软件行业面临三重挑战: 宏观经济承压:全球经济放缓,企业IT预算趋于谨慎; 资本市场收缩:融资环境收紧,盈利能力成为生死线&…...

Linux68 FTP 测试 上传下载
6.在vi编辑器里,哪个命令能将光标移到第200行?( B ) 7.A、200g B、:200 C、g200 D、G200 假如您需要找出 /etc/my.conf 文件属于哪个包 (package) ,您可以执行( D )C A、 rpm -q /etc/my.co…...
横向对比npm和yarn
🔧 基本概况 维度npmYarn所属Node.js 官方工具(npm, Inc.)Meta(Facebook)主导开发初始发布时间2010 年2016 年(为了解决 npm 的一些痛点而诞生)默认安装Node.js 安装后自带需要手动安装最新版本…...
Qt Quick Test模块功能及架构
Qt Quick Test 是专门为测试 QML 应用程序设计的模块,在 Qt 6.0 中得到了显著增强。 一、主要功能/使用方法 核心功能概述 QML 单元测试框架 提供完整的 QML 测试环境 支持测试用例组织和执行 包含 QML 断言函数和测试结果收集 测试类型支持 组件功能测试 用…...
抖音怎么下载没有水印的视频?
你是不是经常在抖音上刷到喜欢的视频,想保存下来却总是带着烦人的水印?无论是想收藏精彩片段,还是二次创作,水印都成了“拦路虎”。别急!今天就来教你3种超简单方法,轻松下载无水印抖音视频,高清…...