类别型特征

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

背景

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

问题

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

  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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何成为快手外卖代理?本地生活服务平台加盟条件解析

近年来,以抖音、快手和小红书等为代表的互联网大厂纷纷进军本地生活领域,改变美团和饿了么二分天下的这一局面的同时,也让本地生活成为了众多创业者眼中的“香饽饽”。其中,快手凭借着其庞大的用户群体,让快手团购外卖…

js使用链表实现音乐播放器(新增,下一首播放,置顶,删除)

什么是链表 链表是一种线性数据结构,与数组类似,它用于存储一系列元素。不过,与数组在内存中连续存储元素不同,链表中的元素(称为节点)在内存中可以是非连续存放的。每个节点包含两部分:一部分…

利用CNN和迁移学习检测太阳能电池板上的尘埃

太阳能电池板已经成为农业、交通、建筑和酒店等多个行业中受欢迎的可再生能源来源。通过利用太阳的能量,我们可以在不损害环境的情况下产生电力。然而,使用太阳能电池板面临着一些挑战,其中最大的之一是它们表面上尘埃的积累。这会显著降低它…

【机器学习】MS_MARCO_Web_Search解析说明

MS MARCO Web Search:引领大型模型与信息检索的新纪元 一、引言:大型模型与信息检索的挑战二、MS MARCO Web Search数据集的特点三、MS MARCO Web Search数据集的应用五、结语 在信息爆炸的时代,如何高效、准确地从海量数据中检索出有价值的信…

Java SE基础知识(13)

知识梳理: package LocalDate;import java.time.DayOfWeek; import java.time.LocalDate; import java.time.Month; import java.time.MonthDay; import java.util.Locale;public class demo1 {public static void main(String[] args) {//1.获取当前时间的日历对象…

构建php环境、安装、依赖、nginx配置、ab压力测试命令、添加php-fpm为系统服务

目录 php简介 官网php安装包 选择下载稳定版本 (建议使用此版本,文章以此版本为例) 安装php解析环境 准备工作 安装依赖 zlib-devel 和 libxml2-devel包。 安装扩展工具库 安装 libmcrypt 安装 mhash 安装mcrypt 安装php 选项含…

VBA技术资料MF158:获取系统的用户名

我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套,分为初级、中级、高级三大部分,教程是对VBA的系统讲解&#…

GBB和Prob IoU[旋转目标检测理论篇]

在开始介绍YOLOv8_obb网络之前,需要先介绍一下arxiv.org/pdf/2106.06072 这篇文章的工作,因为v8_obb就是基于这篇论文提出的GBB和prob IoU来实现旋转目标检测的。 1.高斯分布 一维高斯分布的规律是中间高两边低,且当x为均值的时候取到最大值,表达式如下,标准正态分布图如…

加密资产私钥安全完整手册(一) ,bitget钱包为例

比特币和以太坊等加密货币的兴起开创了数字金融的新时代,但也带来了独特的安全挑战。这些代表现实世界价值的数字资产已成为黑客和窃贼的主要目标。为了安全地应对这种情况,了解私钥的基本概念至关重要。 私钥是加密货币所有权和安全性的基石。它们相当于…

基于图卷积网络的人体3D网格分割

深度学习在 2D 视觉识别任务上取得了巨大成功。十年前被认为极其困难的图像分类和分割等任务,现在可以通过具有类似人类性能的神经网络来解决。这一成功归功于卷积神经网络 (CNN),它取代了手工制作的描述符。 NSDT工具推荐: Three.js AI纹理开…

阿里云和AWS的CDN产品对比分析

在现代互联网时代,内容分发网络(CDN)已成为确保网站和应用程序高性能和可用性的关键基础设施。作为两家领先的云服务提供商,阿里云和Amazon Web Services(AWS)都提供了成熟的CDN解决方案,帮助企业优化网络传输和提升用户体验。我们九河云一直致力于阿里云和AWS云相关业务&#…

【全开源】西陆家政系统源码小程序(FastAdmin+ThinkPHP+原生微信小程序)

打造高效便捷的家政服务平台 一、引言:家政服务的数字化转型 随着人们生活节奏的加快,家政服务需求日益增长。为了满足广大用户对高效、便捷的家政服务的需求,家政小程序系统源码应运而生。这款源码不仅能够帮助家政服务提供商快速搭建自己…

IDEA2023.2单击Setting提示报错:Cannot get children Easy Code

1、单击Setting,不能弹出对话框 2、打开IDE Internal Errors发生错误 原因: 报错信息 "Cannot get children Easy Code" 通常指的是 IntelliJ IDEA 在尝试访问或操作 Easy Code 插件的子设置时遇到了问题。 主要检查是有网络(断断…

R包Colorfindr识别图片颜色|用刀剑神域方式打开SCI科研配色

1.前言 最近忙里偷闲,捣鼓一下配色,把童年回忆里的动漫都搬进来,给科研信仰充值吧~ 提取颜色之前写过一个Py的,那个很准确不过调参会有点麻烦。这里分享一个比较懒人点的R包吧,虽然会有一定误差&#xff…

【XR806开发板试用】基础篇,从零开始搭建一个LCD彩屏时钟(ST7735S驱动)

本文从搭建环境开始,step by step教大家使用XR806实现驱动SPI屏幕(ST7735S驱动),并连接WiFi实现ntp对时,最终实现把时间显示到屏幕上。 #1. 搭建开发环境 1. 安装编译环境所需的依赖包 基于ubuntu 20.04,按…

作业-day-240522

思维导图 使用IO多路复用实现并发 select实现TCP服务器端 #include <myhead.h>#define SER_IP "192.168.125.112" #define SER_PORT 8888int main(int argc, const char *argv[]) {int sfdsocket(AF_INET,SOCK_STREAM,0);if(sfd -1){perror("socket er…

李廉洋:5.29黄金震荡,原油持续走高,今日美盘行情走势分析及策略。

黄金消息面分析&#xff1a;当前美国存在一个令人担忧且未被充分关注的问题&#xff1a;房地产行业低迷、高利率和抵押贷款利率、租金高涨以及美联储的紧缩政策构成了一个恶性循环。由于高房价和高抵押贷款利率&#xff0c;美国住房经济活动远低于两年前的水平。为了让该行业好…

Java特性之设计模式【备忘录模式】

一、备忘录模式 概述 备忘录模式&#xff08;Memento Pattern&#xff09;保存一个对象的某个状态&#xff0c;以便在适当的时候恢复对象&#xff0c;备忘录模式属于行为型模式 备忘录模式允许在不破坏封装性的前提下&#xff0c;捕获和恢复对象的内部状态 主要解决&#xff…

Python爬虫实战(实战篇)—17获取【CSDN某一专栏】数据转为Markdown列表放入文章中

文章目录 专栏导读背景结果预览1、页面分析2、通过返回数据发现适合利用lxmlxpath3、进行Markdown语言拼接总结 专栏导读 在这里插入图片描述 &#x1f525;&#x1f525;本文已收录于《Python基础篇爬虫》 &#x1f251;&#x1f251;本专栏专门针对于有爬虫基础准备的一套基…

【Linux】22. 线程控制

Linux线程控制 POSIX线程库 与线程有关的函数构成了一个完整的系列&#xff0c;绝大多数函数的名字都是以“pthread_”打头的 要使用这些函数库&#xff0c;要通过引入头文<pthread.h> 链接这些线程函数库时要使用编译器命令的“-lpthread”选项 线程创建 pthread_cr…