>백엔드 개발 >파이썬 튜토리얼 >Python 기계 학습에서 범주형 기능을 처리하는 방법은 무엇입니까?

Python 기계 학습에서 범주형 기능을 처리하는 방법은 무엇입니까?

WBOY
WBOY앞으로
2023-06-03 10:45:131085검색

범주형 특성은 직업, 혈액형 등 유한한 범주 집합 내에 속하는 값을 갖는 특성을 말합니다. 원래 입력은 일반적으로 문자열 형식입니다. 대부분의 알고리즘 모델은 숫자 특징의 입력을 허용하지 않습니다. 숫자 범주형 특징은 숫자 특징으로 처리되어 훈련된 모델에 오류가 발생합니다.

Python 기계 학습에서 범주형 기능을 처리하는 방법은 무엇입니까?

Label 인코딩

Label Encoding은 사전을 사용하여 각 카테고리 라벨을 증가하는 정수와 연결합니다. 즉, class_라는 인스턴스 배열에 대한 인덱스를 생성합니다.

Scikit-learn의 LabelEncoder는 범주형 특성 값, 즉 불연속 값이나 텍스트를 인코딩하는 데 사용됩니다. 여기에는 다음과 같은 일반적인 방법이 포함됩니다.

  • fit(y): fit은 빈 사전으로 간주될 수 있고, y는 사전에 강화된 단어로 간주될 수 있습니다.

  • fit_transform(y): 먼저 fit을 수행한 다음 변환하는 것과 같습니다. 즉, y를 사전에 넣은 다음 변환하여 인덱스 값을 얻습니다.

  • inverse_transform(y): 인덱스 값 y를 기반으로 원본 데이터를 가져옵니다.

  • transform(y): y를 인덱스 값으로 변환합니다.

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
city_list = ["paris", "paris", "tokyo", "amsterdam"]
le.fit(city_list)
print(le.classes_)  # 输出为:['amsterdam' 'paris' 'tokyo']
city_list_le = le.transform(city_list)  # 进行Encode
print(city_list_le)  # 输出为:[1 1 2 0]
city_list_new = le.inverse_transform(city_list_le)  # 进行decode
print(city_list_new) # 输出为:['paris' 'paris' 'tokyo' 'amsterdam']

다중 열 데이터 인코딩 방법:

import pandas as pd
from sklearn.preprocessing import LabelEncoder
df = pd.DataFrame({
    'pets': ['cat', 'dog', 'cat', 'monkey', 'dog', 'dog'],
    'owner': ['Champ', 'Ron', 'Brick', 'Champ', 'Veronica', 'Ron'],
    'location': ['San_Diego', 'New_York', 'New_York', 'San_Diego', 'San_Diego',
                 'New_York']
})
d = {}
le = LabelEncoder()
cols_to_encode = ['pets', 'owner', 'location']
for col in cols_to_encode:
    df_train[col] = le.fit_transform(df_train[col])
    d[col] = le.classes_

Pandas의 Factorize()는 시리즈의 명목 데이터를 숫자 집합에 매핑할 수 있으며 동일한 명목 유형은 동일한 숫자에 매핑됩니다. Factorize 함수는 두 개의 요소를 포함하는 튜플을 반환합니다. 첫 번째 요소는 배열이며, 그 요소는 명목 요소가 매핑되는 숫자입니다. 두 번째 요소는 인덱스 유형이며, 여기서 요소는 중복되지 않은 모든 명목 요소입니다.

import numpy as np
import pandas as pd
df = pd.DataFrame(['green','bule','red','bule','green'],columns=['color'])
pd.factorize(df['color'])  #(array([0, 1, 2, 1, 0], dtype=int64),Index(['green', 'bule', 'red'], dtype='object'))
pd.factorize(df['color'])[0] #array([0, 1, 2, 1, 0], dtype=int64)
pd.factorize(df['color'])[1]  #Index(['green', 'bule', 'red'], dtype='object')

Label Encoding은 텍스트를 숫자 값으로 변환할 뿐 텍스트 기능의 문제를 해결하지 않습니다. 모든 레이블은 숫자가 되며 알고리즘 모델은 레이블의 특정 의미에 관계없이 거리를 기준으로 유사한 숫자를 직접 고려합니다. . 이 방법으로 처리된 데이터는 LightGBM과 같은 범주형 속성을 지원하는 알고리즘 모델에 적용될 수 있습니다.

서수 인코딩

서수 인코딩은 m개의 카테고리가 있는 기능의 경우 그에 따라 [0,m-1]의 정수로 매핑됩니다. 물론 Ordinal Encoding은 Ordinal Feature에 더 적합합니다. 즉, 각 기능에는 고유한 순서가 있습니다. 예를 들어, "교육", "학사", "석사", "박사"와 같은 범주의 경우 본질적으로 이러한 논리적 순서가 포함되어 있으므로 자연스럽게 [0,2]로 인코딩될 수 있습니다. 그러나 "색상"과 같은 범주의 경우 "파란색", "녹색" 및 "빨간색"을 각각 [0,2]로 인코딩하는 것은 비합리적입니다. "파란색"과 "빨간색"은 기능에 서로 다른 영향을 미칩니다.

ord_map = {'Gen 1': 1, 'Gen 2': 2, 'Gen 3': 3, 'Gen 4': 4, 'Gen 5': 5, 'Gen 6': 6}
df['GenerationLabel'] = df['Generation'].map(gord_map)

One-Hot Encoding

실제 머신러닝 응용 작업에서 특징은 때때로 연속적인 값이 아닐 수도 있지만, 범주형 값일 수도 있습니다. 예를 들어 성별은 남성과 여성으로 구분될 수 있습니다. 기계 학습 작업에서는 일반적으로 이러한 기능을 디지털화해야 합니다. 예를 들어 다음과 같은 세 가지 기능 속성이 있습니다.

  • Gender: ["male", "female"]

  • Region: [ " Europe", "US", "Asia"]

  • Browser: ["Firefox", "Chrome", "Safari", "Internet Explorer"]

["male"과 같은 특정 샘플의 경우 ", "US", "Internet Explorer"], 이 분류 값의 특성을 디지털화해야 합니다. 가장 직접적인 방법은 직렬화: [0,1,3]을 사용할 수 있습니다. 데이터가 숫자 형태로 변환되더라도 우리 분류기는 위 데이터를 직접 사용할 수 없습니다. 분류기는 데이터가 연속적이고 순서대로 기본 설정되는 경우가 많기 때문입니다. 위의 표현에 따르면 숫자는 순서가 지정되지 않고 무작위로 할당됩니다. 이러한 기능 처리는 기계 학습 알고리즘에 직접 포함될 수 없습니다.

위 문제를 해결하기 위해 One-Hot Encoding을 사용하는 것이 가능한 솔루션 중 하나입니다. 원-핫 인코딩은 1비트 효율적인 인코딩이라고도 합니다. 이 방법은 N 비트 상태 레지스터를 사용하여 N 상태를 인코딩하는 것입니다. 각 상태에는 자체 독립 레지스터 비트가 있으며 언제든지 그 중 하나만 유효합니다. 원-핫 인코딩은 각 기능을 m개의 이진 기능으로 변환합니다. 여기서 m은 해당 기능에 가능한 값의 개수입니다. 또한 이러한 기능은 상호 배타적이며 한 번에 하나만 활성화됩니다. 따라서 데이터가 희박해집니다.

위 문제의 경우 성별 속성은 2차원입니다. 마찬가지로 영역은 3차원이고 브라우저는 4차원입니다. 이런 식으로 위 샘플을 인코딩하려면 [" 남성", "US", "Internet Explorer"] 인코딩, 남성은 [1, 0]에 해당하고, 마찬가지로 US는 [0, 1, 0]에 해당하고, Internet Explorer는 [0, 0, 0, 1]에 해당합니다. 전체 지형지물 디지털화 결과는 [1,0,0,1,0,0,0,0,1]입니다.

Python 기계 학습에서 범주형 기능을 처리하는 방법은 무엇입니까?

원-핫 인코딩을 사용할 수 있는 이유는 무엇인가요?

使用one-hot编码,将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。在回归,分类,聚类等机器学习算法中,特征之间距离的计算或相似度的计算是非常重要的,而我们常用的距离或相似度的计算都是在欧式空间的相似度计算,计算余弦相似性,也是基于的欧式空间。

使用One-Hot编码对离散型特征进行处理可以使得特征之间的距离计算更加准确。比如,有一个离散型特征,代表工作类型,该离散型特征,共有三个取值,不使用one-hot编码,计算出来的特征的距离是不合理。那如果使用one-hot编码,显得更合理。

独热编码优缺点

优点:独热编码解决了分类器不好处理属性数据的问题,在一定程度上也起到了扩充特征的作用。它的值只有0和1,不同的类型存储在垂直的空间。

缺点:当类别的数量很多时,特征空间会变得非常大。在这种情况下,一般可以用PCA(主成分分析)来减少维度。在实际应用中,One-Hot Encoding与PCA结合的方法也非常实用。

One-Hot Encoding的使用场景

独热编码用来解决类别型数据的离散值问题。将离散型特征进行one-hot编码的作用,是为了让距离计算更合理,但如果特征是离散的,并且不用one-hot编码就可以很合理的计算出距离,那么就没必要进行one-hot编码,比如,该离散特征共有1000个取值,我们分成两组,分别是400和600,两个小组之间的距离有合适的定义,组内的距离也有合适的定义,那就没必要用one-hot 编码。

树结构方法,如随机森林、Bagging和Boosting等,在特征处理方面不需要进行标准化操作。对于决策树来说,one-hot的本质是增加树的深度,决策树是没有特征大小的概念的,只有特征处于他分布的哪一部分的概念。

基于Scikit-learn 的one hot encoding

LabelBinarizer:将对应的数据转换为二进制型,类似于onehot编码,这里有几点不同:

  • 可以处理数值型和类别型数据

  • 输入必须为1D数组

  • 可以自己设置正类和父类的表示方式

from sklearn.preprocessing import LabelBinarizer
 
lb = LabelBinarizer()
 
city_list = ["paris", "paris", "tokyo", "amsterdam"]
 
lb.fit(city_list)
print(lb.classes_)  # 输出为:['amsterdam' 'paris' 'tokyo']
 
city_list_le = lb.transform(city_list)  # 进行Encode
print(city_list_le)  # 输出为:
# [[0 1 0]
#  [0 1 0]
#  [0 0 1]
#  [1 0 0]]
 
city_list_new = lb.inverse_transform(city_list_le)  # 进行decode
print(city_list_new)  # 输出为:['paris' 'paris' 'tokyo' 'amsterdam']

OneHotEncoder只能对数值型数据进行处理,需要先将文本转化为数值(Label encoding)后才能使用,只接受2D数组:

import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
def LabelOneHotEncoder(data, categorical_features):
    d_num = np.array([])
    for f in data.columns:
        if f in categorical_features:
            le, ohe = LabelEncoder(), OneHotEncoder()
            data[f] = le.fit_transform(data[f])
            if len(d_num) == 0:
                d_num = np.array(ohe.fit_transform(data[[f]]))
            else:
                d_num = np.hstack((d_num, ohe.fit_transform(data[[f]]).A))
        else:
            if len(d_num) == 0:
                d_num = np.array(data[[f]])
            else:
                d_num = np.hstack((d_num, data[[f]]))
    return d_num
df = pd.DataFrame([
    ['green', 'Chevrolet', 2017],
    ['blue', 'BMW', 2015],
    ['yellow', 'Lexus', 2018],
])
df.columns = ['color', 'make', 'year']
df_new = LabelOneHotEncoder(df, ['color', 'make', 'year'])

基于Pandas的one hot encoding

其实如果我们跳出 scikit-learn, 在 pandas 中可以很好地解决这个问题,用 pandas 自带的get_dummies函数即可

import pandas as pd
 
df = pd.DataFrame([
    ['green', 'Chevrolet', 2017],
    ['blue', 'BMW', 2015],
    ['yellow', 'Lexus', 2018],
])
df.columns = ['color', 'make', 'year']
df_processed = pd.get_dummies(df, prefix_sep="_", columns=df.columns[:-1])
print(df_processed)

get_dummies的优势在于:

  • 本身就是 pandas 的模块,所以对 DataFrame 类型兼容很好

  • 不管你列是数值型还是字符串型,都可以进行二值化编码

  • 能够根据指令,自动生成二值化编码后的变量名

get_dummies虽然有这么多优点,但毕竟不是 sklearn 里的transformer类型,所以得到的结果得手动输入到 sklearn 里的相应模块,也无法像 sklearn 的transformer一样可以输入到pipeline中进行流程化地机器学习过程。

频数编码(Frequency Encoding/Count Encoding)

将类别特征替换为训练集中的计数(一般是根据训练集来进行计数,属于统计编码的一种,统计编码,就是用类别的统计特征来代替原始类别,比如类别A在训练集中出现了100次则编码为100)。这个方法对离群值很敏感,所以结果可以归一化或者转换一下(例如使用对数变换)。未知类别可以替换为1。

频数编码使用频次替换类别。有些变量的频次可能是一样的,这将导致碰撞。尽管可能性不是非常大,没法说这是否会导致模型退化,不过原则上我们不希望出现这种情况。

import pandas as pd
data_count = data.groupby('城市')['城市'].agg({'频数':'size'}).reset_index()
data = pd.merge(data, data_count, on = '城市', how = 'left')

目标编码(Target Encoding/Mean Encoding)

目标编码(target encoding),亦称均值编码(mean encoding)、似然编码(likelihood encoding)、效应编码(impact encoding),是一种能够对高基数(high cardinality)自变量进行编码的方法 (Micci-Barreca 2001) 。

如果某一个特征是定性的(categorical),而这个特征的可能值非常多(高基数),那么目标编码(Target encoding)是一种高效的编码方式。在实际应用中,这类特征工程能极大提升模型的性能。

一般情况下,针对定性特征,我们只需要使用sklearn的OneHotEncoder或LabelEncoder进行编码。

LabelEncoder는 불규칙한 특성 열을 수신하고 이를 0에서 n-1까지의 정수 값으로 변환할 수 있습니다(총 n개의 서로 다른 범주가 있다고 가정). OneHotEncoder는 더미 인코딩 매트릭스를 통해 m*n 스파스를 생성할 수 있습니다(m개의 행이 있다고 가정). 특정 출력 행렬 형식이 희소인지 여부는 희소 매개변수로 제어할 수 있습니다.

질적 특성의 "카디널리티"는 특성이 취할 수 있는 고유한 가능한 값의 총 수를 의미합니다.. 높은 카디널리티의 질적 특성에 직면하여 이러한 데이터 전처리 방법은 종종 만족스러운 결과를 얻지 못합니다.

높은 카디널리티 정성적 특징의 예: IP 주소, 이메일 도메인 이름, 도시 이름, 집 주소, 거리, 제품 번호.

주요 이유:

  • LabelEncoder는 하나의 열만 필요하지만 각 자연수는 서로 다른 의미를 가지며 y에 대해 선형적으로 분리될 수 없습니다. 단순한 모델을 사용하면 과소적합되기 쉽고 다양한 범주 간의 차이를 완전히 포착할 수 없습니다. 복잡한 모델을 사용하면 다른 곳에서 과적합되기 쉽습니다.

  • OneHotEncoder는 카디널리티가 높은 질적 특징을 인코딩하므로 알고리즘 자체가 최적화되지 않는 한(예: SVM) 수만 개의 열이 있는 희소 행렬이 필연적으로 생성되므로 많은 메모리와 교육 시간을 쉽게 소비합니다.

특정 범주형 특성의 카디널리티가 상대적으로 낮은 경우(낮은 카디널리티 특성), 즉 해당 특성의 모든 값을 중복 제거하여 형성된 집합의 요소 수가 상대적으로 적다면 One- 핫 인코딩 방법은 일반적으로 기능을 숫자 값 유형으로 변환하는 데 사용됩니다. 원-핫 인코딩은 데이터 전처리 또는 모델 훈련 중에 완료될 수 있으며, CatBoost는 카디널리티가 낮은 범주형 기능에도 후자의 방법을 사용합니다.

분명히 사용자 ID와 같은 높은 카디널리티 기능 중에서 이 인코딩 방법은 수많은 새로운 기능을 생성하여 차원 재앙을 일으킬 것입니다. 절충 방법은 범주를 제한된 수의 그룹으로 그룹화한 다음 원-핫 인코딩을 수행하는 것입니다. 일반적으로 사용되는 방법은 목표변수 통계(Target Statistics, 이하 TS)에 따라 그룹화하는 방법으로, 각 항목별 목표변수의 기대값을 추정하는 방법이다. 어떤 사람들은 원래 범주형 변수를 대체하기 위해 TS를 새로운 수치 변수로 직접 사용하기도 합니다. 중요한 것은 대수 손실, 지니 계수 또는 평균 제곱 오류를 기반으로 TS 수치 특성에 대한 임계값을 설정함으로써 훈련 세트에 대해 범주를 둘로 나누는 가능한 모든 분할 중에서 최적의 분할을 얻을 수 있다는 것입니다. LightGBM에서 범주형 특징은 그래디언트 부스팅의 각 단계에서 그래디언트 통계(GS)로 표현됩니다. 트리 구축에 중요한 정보를 제공하지만 이 방법에는 다음과 같은 두 가지 단점이 있습니다.

  • 각 범주 기능과 반복의 각 단계에서 GS를 계산해야 하기 때문에 계산 시간이 늘어납니다.

  • 저장 요구 사항 증가 . 범주형 변수의 경우 매번 각 노드의 범주를 저장해야 합니다.

이러한 단점을 극복하기 위해 LightGBM은 일부 정보를 잃는 대신 모든 롱테일 범주를 하나의 범주로 분류합니다. 높은 카디널리티 유형의 기능을 처리할 때 이 방법이 원-핫 인코딩보다 훨씬 낫다고 주장됩니다. TS 기능을 사용하면 카테고리당 하나의 숫자만 계산되어 저장됩니다. 따라서 범주형 특성을 처리하기 위한 새로운 수치 특성으로 TS를 사용하는 것이 가장 효과적이며 정보 손실을 최소화할 수 있습니다. TS는 클릭 예측 작업에도 널리 사용됩니다. 이 시나리오의 범주 기능에는 사용자, 지역, 광고, 광고 게시자 등이 포함됩니다. 다음 논의에서는 TS에 초점을 맞추고 원-핫 인코딩과 GS는 일단 제쳐두겠습니다.

다음은 계산 공식입니다.

여기서 n은 특정 기능에 대한 값의 수를 나타내고,

는 특정 기능 값에 대한 긍정적인 레이블 수를 나타내고, mdl은 최소 임계값이며, 숫자는 샘플 수가 다음보다 작습니다. 이 값의 기능 범주는 무시되며 우선 순위는 레이블의 평균입니다. 회귀 문제를 처리하는 경우 해당 기능 아래 레이블 값의 평균/최대로 처리될 수 있습니다. k 분류 문제의 경우 해당 k-1 특징이 생성됩니다.

이 방법은 과적합을 방지하기 위해 다음 방법도 사용됩니다.

  • 정규항 a의 크기를 늘리세요

  • 훈련 세트의 이 열에 노이즈를 추가하세요

  • 크로스오버 사용

대상 코딩이 지도 코딩 방법인지 확인합니다. 올바르게 사용하면 예측 모델의 정확도를 효과적으로 향상시킬 수 있으며 이에 대한 핵심은 이를 도입하는 것입니다. 과적합 문제를 피하기 위한 코딩 프로세스 정규화.

예를 들어 카테고리 A는 200개의 태그 1, 300개의 태그 2, 500개의 태그 3에 해당합니다. 2/10, 3/10, 3/6으로 코딩할 수 있습니다. 중간에서 가장 중요한 것은 과적합을 피하는 방법입니다(원래 대상 인코딩은 모든 훈련 세트 데이터와 레이블을 직접 인코딩하므로 얻은 인코딩 결과가 훈련 세트에 너무 의존하게 됩니다). 일반적인 해결책은 2를 사용하는 것입니다. 교차 검증 수준은 목표 평균을 찾습니다.

  • 把train data划分为20-folds (举例:infold: fold #2-20, out of fold: fold #1)

  • 计算 10-folds的 inner out of folds值 (举例:使用inner_infold #2-10 的target的均值,来作为inner_oof #1的预测值)

  • 对10个inner out of folds 值取平均,得到 inner_oof_mean

  • 将每一个 infold (fold #2-20) 再次划分为10-folds (举例:inner_infold: fold #2-10, Inner_oof: fold #1)

  • 计算oof_mean (举例:使用 infold #2-20的inner_oof_mean 来预测 out of fold #1的oof_mean

  • 将train data 的 oof_mean 映射到test data完成编码

比如划分为10折,每次对9折进行标签编码然后用得到的标签编码模型预测第10折的特征得到结果,其实就是常说的均值编码。

目标编码尝试对分类特征中每个级别的目标总体平均值进行测量。当数据量较少时,每个级别的数据量减少意味着估计的均值与真实均值之间的差距增加,方差也会更大。

from category_encoders import TargetEncoder
import pandas as pd
from sklearn.datasets import load_boston
# prepare some data
bunch = load_boston()
y_train = bunch.target[0:250]
y_test = bunch.target[250:506]
X_train = pd.DataFrame(bunch.data[0:250], columns=bunch.feature_names)
X_test = pd.DataFrame(bunch.data[250:506], columns=bunch.feature_names)
# use target encoding to encode two categorical features
enc = TargetEncoder(cols=['CHAS', 'RAD'])
# transform the datasets
training_numeric_dataset = enc.fit_transform(X_train, y_train)
testing_numeric_dataset = enc.transform(X_test)

Beta Target Encoding

Kaggle竞赛Avito Demand Prediction Challenge 第14名的solution分享:14th Place Solution: The Almost Golden Defenders。和target encoding 一样,beta target encoding 也采用 target mean value (among each category) 来给categorical feature做编码。不同之处在于,为了进一步减少target variable leak,beta target encoding发生在在5-fold CV内部,而不是在5-fold CV之前:

  • 把train data划分为5-folds (5-fold cross validation)

  • target encoding based on infold data

  • train model

  • get out of fold prediction

同时beta target encoding 加入了smoothing term,用 bayesian mean 来代替mean。Bayesian mean (Bayesian average) 的思路:某一个category如果数据量较少(

另外,对于target encoding和beta target encoding,不一定要用target mean (or bayesian mean),也可以用其他的统计值包括 medium, frqequency, mode, variance, skewness, and kurtosis — 或任何与target有correlation的统计值。

# train -> training dataframe
# test -> test dataframe
# N_min -> smoothing term, minimum sample size, if sample size is less than N_min, add up to N_min 
# target_col -> target column
# cat_cols -> categorical colums
# Step 1: fill NA in train and test dataframe
# Step 2: 5-fold CV (beta target encoding within each fold)
kf = KFold(n_splits=5, shuffle=True, random_state=0)
for i, (dev_index, val_index) in enumerate(kf.split(train.index.values)):
    # split data into dev set and validation set
    dev = train.loc[dev_index].reset_index(drop=True) 
    val = train.loc[val_index].reset_index(drop=True)
        
    feature_cols = []    
    for var_name in cat_cols:
        feature_name = f'{var_name}_mean'
        feature_cols.append(feature_name)
        
        prior_mean = np.mean(dev[target_col])
        stats = dev[[target_col, var_name]].groupby(var_name).agg(['sum', 'count'])[target_col].reset_index()           
   
        ### beta target encoding by Bayesian average for dev set 
        df_stats = pd.merge(dev[[var_name]], stats, how='left')
        df_stats['sum'].fillna(value = prior_mean, inplace = True)
        df_stats['count'].fillna(value = 1.0, inplace = True)
        N_prior = np.maximum(N_min - df_stats['count'].values, 0)   # prior parameters
        dev[feature_name] = (prior_mean * N_prior + df_stats['sum']) / (N_prior + df_stats['count']) # Bayesian mean
        ### beta target encoding by Bayesian average for val set
        df_stats = pd.merge(val[[var_name]], stats, how='left')
        df_stats['sum'].fillna(value = prior_mean, inplace = True)
        df_stats['count'].fillna(value = 1.0, inplace = True)
        N_prior = np.maximum(N_min - df_stats['count'].values, 0)   # prior parameters
        val[feature_name] = (prior_mean * N_prior + df_stats['sum']) / (N_prior + df_stats['count']) # Bayesian mean
        
        ### beta target encoding by Bayesian average for test set
        df_stats = pd.merge(test[[var_name]], stats, how='left')
        df_stats['sum'].fillna(value = prior_mean, inplace = True)
        df_stats['count'].fillna(value = 1.0, inplace = True)
        N_prior = np.maximum(N_min - df_stats['count'].values, 0)   # prior parameters
        test[feature_name] = (prior_mean * N_prior + df_stats['sum']) / (N_prior + df_stats['count']) # Bayesian mean
        
        # Bayesian mean is equivalent to adding N_prior data points of value prior_mean to the data set.
        del df_stats, stats
    # Step 3: train model (K-fold CV), get oof predictio

M-Estimate Encoding

M-Estimate Encoding 相当于 一个简化版的Target Encoding:

其中????+代表所有正Label的个数,m是一个调参的参数,m越大过拟合的程度就会越小,同样的在处理连续值时????+可以换成label的求和,????+换成所有label的求和。

James-Stein Encoding

一种基于目标的算法是 James-Stein 编码。算法的思想很简单,对于特征的每个取值 k 可以根据下面的公式获得:

其中B由以下公式估计:

但是它有一个要求是target必须符合正态分布,这对于分类问题是不可能的,因此可以把y先转化成概率的形式。在实际操作中,可以使用网格搜索方法来选择一个较优的B值。

Weight of Evidence Encoder

Weight Of Evidence 同样是基于target的方法。

使用WOE作为变量,第i类的WOE等于:

WOE特别合适逻辑回归,因为Logit=log(odds)。WOE编码的变量被编码为统一的维度(是一个被标准化过的值),变量之间直接比较系数即可。

Leave-one-out Encoder (LOO or LOOE)

这个方法类似于SUM的方法,只是在计算训练集每个样本的特征值转换时都要把该样本排除(消除特征某取值下样本太少导致的严重过拟合),在计算测试集每个样本特征值转换时与SUM相同。可见以下公式:

Binary Encoding

使用二进制编码对每一类进行编号,使用具有log2N维的向量对N类进行编码。以 (0,0) 为例,它表示第一类,而 (0,1) 表示第二类,(1,0) 表示第三类,(1,1) 则表示第四类

Hashing Encoding

类似于One-hot encoding,但是通过hash函数映射到一个低维空间,并且使得两个类对应向量的空间距离基本保持一致。使用低维空间来降低了表示向量的维度。

特征哈希可能会导致要素之间发生冲突。一个哈希编码的好处是不需要指定或维护原变量与新变量之间的映射关系。因此,哈希编码器的大小及复杂程度不随数据类别的增多而增多。

Probability Ratio Encoding

和WOE相似,只是去掉了log,即:

Sum Encoder(Deviation Encoder, Effect Encoder)

해당 특성 값 아래의 레이블(또는 기타 관련 변수)의 평균값과 전체 레이블의 평균값의 차이를 비교하여 특정 특성에 대해 합 인코딩을 수행합니다. . 기능을 인코딩합니다. 세부 사항이 제대로 수행되지 않으면 이 방법은 과적합되기 매우 쉬우므로 특징을 인코딩하려면 Leave-One-Out 방법 또는 5겹 교차 검증과 결합해야 합니다. 과적합을 방지하기 위해 분산을 기반으로 페널티 항을 추가하는 방법도 있습니다.

Helmert 인코딩

Helmert 인코딩은 계량경제학에서 흔히 사용됩니다. Helmert 인코딩 후(범주형 특성의 각 값은 Helmert 행렬의 행에 해당함) 선형 모델의 인코딩된 변수 계수는 범주 변수의 특정 범주 값이 주어지면 종속 변수의 평균 값과 차이를 반영할 수 있습니다. 해당 범주의 다른 범주에 대한 값이 제공된 종속 변수의 평균입니다.

Helmet 인코딩은 One-Hot Encoding과 Sum Encoder 다음으로 가장 널리 사용되는 인코딩 방법입니다. Sum Encoder와는 달리 특정 특성 값 하에서 해당 레이블(또는 기타 관련 변수)의 평균값과 차이를 비교합니다. 모든 특성의 평균이 아니라 이전 특성의 평균을 의미합니다. 이 기능은 과적합되기 쉽습니다.

CatBoost Encoding

가능한 값의 수가 원-핫 최대값보다 큰 범주형 변수의 경우 CatBoost는 평균 인코딩과 유사하지만 과적합을 줄일 수 있는 매우 효과적인 인코딩 방법을 사용합니다. 구체적인 구현 방법은 다음과 같습니다.

  • 입력 샘플 세트를 무작위로 정렬하고 여러 그룹의 무작위 배열을 생성합니다.

  • 부동 소수점 또는 속성 값 태그를 정수로 변환합니다.

  • 모든 분류 특성값 결과를 다음 수식에 따라 수치 결과로 변환합니다.

CountInClass는 현재 분류 ​​특성 값에서 표시 값이 1인 샘플의 수를 나타내며, Prior는 초기 매개변수에 따라 결정되는 분자의 초기 값입니다. TotalCount는 현재 샘플 자체를 포함하여 현재 샘플과 분류 특성 값이 동일한 모든 샘플의 수를 나타냅니다.

CatBoost 처리 요약 범주형 기능:

먼저 데이터의 일부 통계를 계산합니다. 카테고리의 발생 빈도를 계산하고, 하이퍼파라미터를 추가하고, 새로운 수치 특성을 생성합니다. 이 전략에서는 동일한 레이블이 있는 데이터를 함께 정렬할 수 없으며(즉, 모두 0이 먼저, 그 다음에는 모두 1이 됨) 학습 전에 데이터 세트를 중단해야 합니다.

둘째, 데이터의 다양한 순열을 사용합니다(실제로는 4개). 각 라운드마다 나무를 만들기 전에 주사위를 던져 나무를 만드는 데 사용할 배열을 결정합니다.

세 번째 요점은 범주형 특성의 다양한 조합을 시도해 보는 것입니다. 예를 들어, 색상과 유형의 조합은 파란색 개와 유사한 특징을 형성할 수 있습니다. 결합해야 하는 범주형 기능의 수가 증가하면 catboost는 일부 조합만 고려합니다. 첫 번째 노드를 선택할 때 A와 같은 하나의 특징만 고려됩니다. 두 번째 노드를 생성할 때 A와 범주형 특성의 조합을 고려하고 가장 좋은 것을 선택합니다. 이런 식으로 그리디 알고리즘을 사용하여 조합을 생성합니다.

넷째, 성별처럼 차원이 매우 작지 않은 한 원-핫 벡터를 직접 생성하는 것은 권장하지 않습니다.

위 내용은 Python 기계 학습에서 범주형 기능을 처리하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제