类别型特征

news2024/9/26 1:20:45

#机器学习 #深度学习 #基础知识 #特征工程 #数据编码

背景

在现实生活中,我们面对的数据类型有很多,其中有的数据天然为数值类型具备数值意义,那么可以很自然地和算法结合,但是大部分数据他没有天然的数值意义,那么将他们送入到算法前,就需要对数据进行编码处理,将其转换为数值类型,才可以送入算法进行运算.

问题

处理一个这样算法问题时,首先我们需要确认所处理的数据是什么类型的,是否可以直接输入模型,如果不能,那么我们需要根据数据本身的特点,然后结合算法的适配的格式,去对数据进行编码处理.因此,我们需要依次思考以下的几个问题:

  1. 常见的类别数据有哪些形式?其中有哪些是需要进行编码的?
  2. 哪些算法能接收未经编码的类别型特征?哪些算法不能?
  3. 常见的编码类型及其优缺点?如何选择适合的编码方式?

解决方案

常见的类别特征有哪些?其中有哪些是需要进行编码的?

类别型特征是指在数据集中表示某种类别或属性的特征。它包含有限个离散的取值,通常用于描述无序的分类或标签信息。类别型特征没有固定的数值间隔和数值运算意义,只表示不同类别之间的区别和关系

例如,性别、颜色、地区、职业、喜好程度、股票种类、专业等都可以是类别型特征。性别可以有两个取值:男和女;颜色可以有多个取值:红、蓝、绿等;地区可以有多个取值:东、南、西、北等;职业可以有多个取值:医生、教师、工程师等;问卷调查中,对一件事的喜好程度分为厌恶、无感、较喜欢、喜欢、特别喜欢等;股票可以分为煤炭,光伏,消费,白酒,医疗等等不同的板块;高考报志愿时,专业可以分为计算机科学,基础物理学,临床医学,兽医学,法律,文学等等.

总结来看,这些类别特征按照是否有序可以分为: 有序类别特征(Ordinal Categorical Features)是指类别之间存在自然顺序或等级关系的特征。这类特征的值可以进行排序,但不能直接进行数值运算;无序类别特征(Nominal Categorical Features)是指类别之间没有自然顺序或等级关系的特征。这类特征的值只是表示不同的类别,不存在排序关系。要是按照类别的数量来来分:高基类类别特征,具有大量唯一值的类别,特征类别总数很大;低基类类别特征,具有少量唯一值的类别,特征类别总数较少.

关于哪些类别特征需要编码,这个问题其实需要结合所采用的算法统筹考虑才有实际意义.但是,单从类别特征的分类上来考虑,可以划分为四种类型,它们的编码难点可以总结为下:

有序无序
低基类保留类别顺序关系,保证类别均衡保证类别间独立,保证类别均衡
高基类保留类别关系,防止过拟合,解决稀疏性保证类别间独立,解决稀疏性

哪些算法能接收未经编码的类别特征?哪些算法不能?

首先,没有经过编码的数据大多数为字符串类型.不同的算法所接受的数据格式是不同的,所以根据具体算法接收的数据格式来看.一般来说,只有能够直接依据类别划分就能进行运行的算法可以不用进行编码,决策树类算法(决策树,随机森林),规则基础算法(C5.0)以及基于统计概率的部分贝叶斯分类算法,其余的算法都需要对类别型特征进行编码处理后才能让算法正常运行.

常见的编码类型及其优缺点?如何选择适合的编码方式?

标签编码

不适用于高基类类别特征,并且编码后的自然数对于回归任务来说是线性不可分的,即自然数之间的关系不能代表编码前的类别关系.

哈稀编码

将类别特征通过哈希函数映射到固定数量的哈希桶中。这种方法在类别数量非常多时可以减小维度,但可能引入哈希冲突。

独热编码

独热编码(One-Hot Encoding),又称一位有效编码,其方法是使用N位状态寄存器来对N个状态进行编码,每个状态都有它独立的寄存器位,并且在任意时候,其中只有一位有效。这个方法能很好的保证编码后,各个类别特征的独立性,但是面对高基类类型特征时,会比较稀疏从而浪费资源.

计数编码

计数编码(Count Encoding,也称频率编码)的过程,可以按照以下步骤进行:

  1. 原始类别数据:列出原始的类别数据。
  2. 计算类别频数:计算每个类别在数据集中出现的频数。
  3. 替换类别值:用类别的频数替换原始的类别值。

假设我们有一个类别特征 "Color",它有以下类别值:红色、绿色、蓝色、黄色、绿色、红色、蓝色。我们将计算这些颜色频数得:红色:2,绿色:2,蓝色:2,黄色:1。这种编码方式的问题显而易见,编码只关注了类别在数据集中出现的频次,但是忽略了类别本身的意义.所以,这种方式可能只适用于模型不关心类别意义,而关注类别统计属性的模型中.

直方图编码

实际上直方图编码,也是基于统计的编码,只不过它统计的不是单纯类别样本出现的次数,而是某一种特征在不同类别中的出现频次.这样我们通过先验的统计这些每个类别中这些特征的频次,然后观察样本中表现出的特征,来预测这个样本的类别.直方图编码能清晰看出特征下不同类别对不同预测标签的贡献度,缺点在于:使用了标签数据,若训练集和测试集的类别特征分布不一致,那么编码结果容易引发过拟合。此外,直方图编码出的特征数量是分类标签的类别数量,若标签类别很多,可能会给训练带来空间和时间上的负担

WOE编码

权重证据编码(Weight of Evidence Encoding, WOE)的过程,我们可以按照以下步骤进行:

  1. 原始类别数据:列出原始的类别数据和目标变量。
  2. 计算类别的WOE值:计算每个类别的WOE值。
  3. 替换类别值:用类别的WOE值替换原始的类别值。

假设我们有一个类别特征 "Color",它有以下类别值:红色、绿色、蓝色、黄色,并且有一个二进制目标变量 "Target"。

权重证据(WOE)的计算公式为: 

WOE=ln(\frac{Good_{dist}}{Bad_{dist}})

其中,"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=ln(\frac{\frac{1}{3}}{\frac{1}{4}})=ln(\frac{4}{3})\approx 0.2877
  • 绿色:WOE=ln(\frac{\frac{1}{3}}{\frac{1}{4}})=ln(\frac{4}{3})\approx 0.2877
  • 蓝色:WOE=ln(\frac{\frac{1}{3}}{\frac{1}{4}})=ln(\frac{4}{3})\approx 0.2877
  • 黄色:WOE=ln(\frac{\frac{0}{3}}{\frac{1}{4}})=ln(\frac{4}{0})\approx -\infty (注意:在实际应用中我们会处理这种情况)

透过公式,我们可以把WOE理解成:每个分组内坏客户分布相对于优质客户分布之间的差异性。

WOE存在几个问题:

  1. 分母可能为0.
  2. 没有考虑不同类别数量的大小带来的影响,可能某类数量多,但最后计算出的WOE跟某样本数量少的类别的WOE一样。
  3. 只针对二分类问题。
  4. 训练集和测试集可能存在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 LabelBinarizer
 
lb = 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(\frac{Positive Rate}{Negative Rate})

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1705771.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

php -v在cmd中正常显示 在vscode中却报错

效果展示 原因 在vscode中 终端是 PowerShell PowerShell 默认情况下它不会继承系统的PATH环境变量 解决方案 使用CMD作为终端 打开VSCode设置(File > Preferences > Settings 或 Ctrl,)。搜索 terminal.integrated.shell.windows。更改其值…

vue3主题切换按钮与功能实现

代码: <template><div class"slideThree"><label class"theme-switch"><inputtype"checkbox"class"checkbox"v-model"isChecked"change"setTheme"id"slideThree"name"check…

光伏组件积灰检测系统

光伏组件积灰检测系统是一种专门用于监测光伏组件表面灰尘积累情况的设备。以下是关于该系统的详细信息和特点&#xff1a; 系统概述 光伏组件积灰检测系统安装在光伏板的框架上&#xff0c;通过实时监测光伏组件表面的灰尘厚度、分布情况和清洁度&#xff0c;为运维人员提供…

揭秘爬虫技术:从请求到存储的全方位解析

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、爬虫初探&#xff1a;请求与响应 二、数据解析&#xff1a;从混乱中提炼价值 三、数据…

CentOS 7如何使用systemctl管理应用

说明&#xff1a;本文介绍如何使用systemctl命令的方式来启动、查看、停止和重启应用&#xff0c;以安装后的prometheus、alertmanager为例&#xff1b; Step1&#xff1a;创建文件 在系统/etc/systemd/system/路径下&#xff0c;创建一个xxx.service文件&#xff0c;该文件内…

配置环境变量

配置环境变量$(xxxx)&#xff0c;代表宏 32位操作系统&#xff0c;请自觉将文中路径中所有的x64换成x86。 %符号表示引用系统环境变量或用户自定义的环境变量 如果你想将某个文件夹添加到Visual Studio的路径中&#xff0c;你可以在环境变量中添加%FolderName%&#xff0c;其…

使用阿里云OSS实现视频上传功能

目录 前言 视频上传 前言 阿里云对象存储服务&#xff08;OSS&#xff09;作为一种高可用、高扩展性的云端存储服务&#xff0c;为开发者提供了便捷、安全的对象存储解决方案。本文将介绍如何利用阿里云OSS实现视频上传功能。 视频上传 前期准备请看阿里云OSS文件上传和下载…

基于mybatis-plus的多语言扩展

概览 对于表中字段&#xff0c;需要实现多语言的方案探讨&#xff1a; 1.表中横向扩展多个字段分别存储中文&#xff0c;英文&#xff0c;俄语等语言字段&#xff0c;查询时&#xff0c;根据需要查询的语言&#xff0c;进行查询 2.增加一张多语言表&#xff0c;存储多语言信…

RedHat9网络配置设计

目录 一、实验目的 二、实验过程 1、配置新网络接口 2、多网卡配置网络 3、网络接口的绑定&#xff0c;进行远程访问 4、配置网络接口的组合 一、实验目的 本次实验的目的是使用nmcli命令工具配置网络&#xff0c;ens160配置多个网卡&#xff0c;进行网络接口的绑定与组合…

iPhone“已删除”照片被恢复,苹果到底有没有后门?

继微软本周推出的Windows“回忆”功能引发隐私焦虑&#xff0c;遭马斯克和安全大咖们猛烈抨击后&#xff0c;苹果iPhone手机近日也曝出了类似的“记忆门”。 删除十几年的iPhone照片被恢复 近日&#xff0c;有苹果手机用户更新了苹果上周发布的iOS 17.5系统后&#xff0c;意外…

ChatGPT越来越懒,都学会反过来PUA人类了

OpenAI 表示自 11 月 11 日以来&#xff0c;他们就没有更新过模型&#xff0c;模型行为是不可预测的&#xff0c;他们正在研究如何修复。 不知你有没有注意到&#xff0c;最近一段时间&#xff0c;GPT-4 变得有些「懒惰」&#xff0c;现在的它&#xff0c;老是拒绝执行某些任务…

关于亚马逊、速卖通、虾皮、Lazada等平台自养号测评IP的重要性

在自养号测评中&#xff0c;IP的纯净度是一个至关重要的问题&#xff0c;它直接关系到账号的安全性和稳定性如果使用了被平台识别为异常或存在风险的IP地址&#xff0c;那么账号可能会面临被封禁的风险。这将对账号的正常使用和测评过程中造成严重影响。而使用纯净的IP地址&…

oracle准确记录数据提交时间

注意&#xff1a;mysql中的默认值同样记录的是dml操作发出时的时间&#xff0c;并且没有找到mysql中准确记录commit时间的方法。 oracle中数据发生变动时&#xff0c;如何准确记录发生变动时的时间。一般会使用ts字段&#xff0c;该字段使用默认值&#xff0c;default to_char…

【JAVA WEB实用与优化技巧】如何自己封装一个自定义UI的Swagger组件,包含Swagger如何处理JWT无状态鉴权自动TOKEN获取

目录 一、Swagger 简介1. 什么是 Swagger&#xff1f;2. 如何使用 Swagger3. Springboot 中swagger的使用示例1. maven 引入安装2. java配置 二、Swagger UI存在的缺点1.不够方便直观2.请求的参数没有缓存3.不够美观4.如果是JWT 无状态登录&#xff0c;Swagger使用起来就没有那…

简化跨网文件传输摆渡过程,降低IT人员工作量

在当今数字化时代&#xff0c;IT企业面临着日益增长的数据交换需求。随着网络安全威胁的不断演变&#xff0c;网关隔离成为了保护企业内部网络不受外部威胁的重要手段。然而&#xff0c;隔离的同时&#xff0c;企业也需要在不同网络间安全、高效地传输文件&#xff0c;这就催生…

harmony开发遇到的问题

arkt-no-props-by-indexProperty ‘name’ has no initializer and is not definitely assigned in the constructor.arkts-no-any-unknown typescript 中的报错 Property ‘name’ has no initializer and is not definitely assigned in the construc… ArkTs编译常见错误汇…

全网爆火Remini 粘土滤镜风格,我用ComfyUI一键生成了(保姆级教程)!

一、火爆全网的Remini&#xff01; Remini真的火爆了&#xff01;最近大家的朋友应该都被粘土滤镜刷屏了。 小红书上粘土滤镜、粘土特效的帖子动不动就是几百万浏览量&#xff0c;几千赞。 在有些电商平台上还有人接单&#xff0c;帮忙定制remini粘土风格的照片&#xff01; …

Shell编程之正则表达式与文本处理器

一、正则表达式 之前学习了 Shell 脚本的基础用法&#xff0c;已经可以利用条件判断、循环等语句编辑 Shell 脚本。接下来我们将开始介绍一个很重要的概念——正则表达式&#xff08;RegularExpression&#xff0c;RE&#xff09;。 1.1正则表达式概述 下面先来了解一下正则表…

软件产品测试报告模版分享,获取专业测试报告所需时间和费用

软件产品测试是一个系统性的、全面的质量保障过程&#xff0c;旨在发现和修复软件产品中的缺陷和错误&#xff0c;以确保软件的功能完善、性能卓越、安全可靠。 软件产品测试报告是软件测试过程中的重要文档之一&#xff0c;它主要记录了测试人员对软件产品进行测试的结果和结…

LLM 大模型学习必知必会系列(十三):基于SWIFT的VLLM推理加速与部署实战

LLM 大模型学习必知必会系列(十三)&#xff1a;基于SWIFT的VLLM推理加速与部署实战 1.环境准备 GPU设备: A10, 3090, V100, A100均可. #设置pip全局镜像 (加速下载) pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ #安装ms-swift pip install ms-…