分类问题中,经常会碰到类别极度不平衡的情况,这个时候可对样本进行上下采样,让训练数据集的类别接近平衡即可。
数据格式是一个dataframe,数据分为两类:多数类别和少数类别,数据量相差大。一般而言一个数据集中负样本数量远远大于正样本,故数据预处理已将多数类别的Label标记为0,少数类别的Label标记为1。以下分别是python实现采样代码:
一.下采样
下采样则是从多数量的类别中随机抽取样本(抽取的样本数量与少数类别样本量一致)从而减少多数量的类别样本数据,使数据达到平衡的方式。
import numpy as np
import pandas as pd
#下采样
def lower_sample_data(df, percent=1):
'''
percent:多数类别下采样的数量相对于少数类别样本数量的比例
'''
data1 = df[df['Label'] == 0] # 将多数量的类别样本放在data1
data0 = df[df['Label'] == 1] # 将少数量的类别样本放在data0
index = np.random.randint(
len(data1), size=percent * (len(df) - len(data1))) # 随机给定下采样取出样本的序号
lower_data1 = data1.iloc[list(index)] # 下采样
return(pd.concat([lower_data1, data0]))
np.random.seed(28)
arr1 = np.random.randint(6, size=(100, 5))
arr2 = np.random.randint(1000, 1010, size=(10, 5))
columns = ['A', 'B', 'C', 'D', 'E']
df1 = pd.DataFrame(arr1, columns=columns)
df1['Label'] = 0
df2 = pd.DataFrame(arr2, columns=columns)
df2['Label'] = 1
df = pd.concat([df1, df2])
print(lower_sample_data(df))
二.上采样
上采样则是从少数量的类别中随机抽取样本(抽取的样本数量与多数类别样本量一致,或着增加一定的比例,可控制)从而增多多数量的类别样本数据,使数据达到平衡的方式。
import numpy as np
import pandas as pd
def up_sample_data(df, percent=0.2):
'''
percent:少数类别样本数量的重采样的比例,可控制,一般不超过0.5,以免过拟合
'''
data1 = df[df['Label'] == 0] # 将多数类别的样本放在data1
data0 = df[df['Label'] == 1] # 将少数类别的样本放在data0
index = np.random.randint(
len(data0), size= int(percent * (len(df) - len(data0)))) # 随机给定上采样取出样本的序号
up_data0 = data0.iloc[list(index)] # 上采样
return(pd.concat([up_data0, data1]))
np.random.seed(28)
arr1 = np.random.randint(6, size=(100, 5))
arr2 = np.random.randint(1000, 1010, size=(10, 5))
columns = ['A', 'B', 'C', 'D', 'E']
df1 = pd.DataFrame(arr1, columns=columns)
df1['Label'] = 0
df2 = pd.DataFrame(arr2, columns=columns)
df2['Label'] = 1
df = pd.concat([df1, df2])
三.当正负样本差异非常极端的时候,上、下采样一起结合,少数量的样本重采样(复制)一定比例,多数量的类别样本随机减少一定比例样本,让两者达到平衡。
import numpy as np
import pandas as pd
def up_lower_sample_data(df, up_percent=0.2,lower_percent=0.5):
'''
percent:多数类别下采样的数量相对于少数类别样本数量的比例
'''
data1 = df[df['Label'] == 0] # 将多数类别的样本放在data1
data0 = df[df['Label'] == 1] # 将少数类别的样本放在data0
up_index = np.random.randint(
len(data0), size= int(up_percent * (len(df) - len(data0)))) # 随机给定上采样取出样本的序号
up_data0 = data0.iloc[list(up_index)] # 上采样
lower_index = np.random.randint(
len(data1), size=int(lower_percent * (len(df) - len(data0)))) # 随机给定下采样取出样本的序号
lower_data1 = data1.iloc[list(lower_index)] # 下采样
return(pd.concat([up_data0, lower_data1]))
np.random.seed(28)
arr1 = np.random.randint(6, size=(100, 5))
arr2 = np.random.randint(1000, 1010, size=(10, 5))
columns = ['A', 'B', 'C', 'D', 'E']
df1 = pd.DataFrame(arr1, columns=columns)
df1['Label'] = 0
df2 = pd.DataFrame(arr2, columns=columns)
df2['Label'] = 1
df = pd.concat([df1, df2])
print(up_lower_sample_data(df))
本文参考以下连接,然后加深一步将上采样和两者结合代码写出,根据上下采样的原理,用python代码实现,如有疑惑可指正,谢谢!