类别不平衡:python代码实现上采样、下采样以及上采样结合

分类问题中,经常会碰到类别极度不平衡的情况,这个时候可对样本进行上下采样,让训练数据集的类别接近平衡即可。

数据格式是一个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代码实现,如有疑惑可指正,谢谢!

参考:https://blog.csdn.net/xiaoxy97/article/details/82898812?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight

 

  • 5
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
采样是一种常见的解决类别平衡问题的方法之一。下面是一个简单的 Python 代码示例,用于在序列不平衡的情况下进行下采样: ```python import random def downsample(X, y, target_size): """ X: 输入序列 y: 对应的标签 target_size: 下采样后的目标序列大小 """ class_counts = {} for label in y: if label not in class_counts: class_counts[label] = 0 class_counts[label] += 1 new_X = [] new_y = [] for label in class_counts: if class_counts[label] >= target_size: # 如果该类别的样本数已经大于等于目标样本数,直接加入新序列 indices = [i for i, x in enumerate(y) if x == label] new_X.extend([X[i] for i in indices[:target_size]]) new_y.extend([label] * target_size) else: # 否则对该类别进行下采样 indices = [i for i, x in enumerate(y) if x == label] new_X.extend([X[i] for i in indices]) new_y.extend([label] * len(indices)) while len(new_y) < target_size: idx = random.randint(0, len(indices)-1) new_X.append(X[indices[idx]]) new_y.append(label) return new_X, new_y ``` 使用示例: ```python X = ["hello", "world", "how", "are", "you", "doing", "today", "I", "am", "fine"] y = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1] new_X, new_y = downsample(X, y, 4) print(new_X) # ["hello", "world", "how", "are", "I", "am", "fine"] print(new_y) # [0, 0, 0, 0, 1, 1, 1] ``` 在上面的示例中,我们将目标序列大小设置为 4,由于类别 0 中的样本数大于 4,因此我们直接选择了前 4 个样本,类别 1 中的样本数小于 4,因此我们对其进行了下采样,最终得到了大小为 4 的新序列。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值