Python:数据抽样平衡方法重写

之前在R里面可以通过调用Rose这个package调用数据平衡函数,这边用python改写了一下,也算是自我学习了。

R:

#设定工作目录
setwd(path)
# 安装包
install.packages("ROSE")
library(ROSE)
#检查数据
data(hacide)
table(hacide.train$cls)
  0     1 
980    20

过抽样实现:

data_balanced_over <- ovun.sample(cls ~ ., data = hacide.train, method = "over",N = 1960)$data
table(data_balanced_over$cls)
0    1 
980 980

这边需要注意是ovun不是over


欠采样实现:

data_balanced_under <- ovun.sample(cls ~ ., data = hacide.train, method = "under", N = 40, seed = 1)$data
table(data_balanced_under$cls)
0    1 
20  20

这边需要注意的是欠采样是不放回采样,同时对数据信息的损失也是极大的


组合采样实现:

data_balanced_both <- ovun.sample(cls ~ ., data = hacide.train, method = "both", p=0.5, N=1000, seed = 1)$data
table(data_balanced_both$cls)
0    1 
520 480

method的不同值代表着不同的采样方法,p这边是控制正类的占比,seed保证抽取样本的固定,也就是种子值。



在python上,我也没有发现有现成的package可以import,所以就参考了R的实现逻辑重写了一遍,新增了一个分层抽样group_sample,删除了过采样,重写了组合抽样combine_sample,欠抽样under_sample:

# -*- coding:utf-8 -*-
import pandas as pd
import random as rd
import numpy as np
import math as ma


class sample_s(object):
    def __init__(self):
        ''''this is my pleasure'''

    def group_sample(self, data_set, label, percent=0.1):
        # 分层抽样
        # data_set:数据集
        # label:分层变量
        # percent:抽样占比
        # q:每次抽取是否随机,null为随机
        # 抽样根据目标列分层,自动将样本数较多的样本分层按percent抽样,得到目标列样本较多的特征欠抽样数据
        x = data_set
        y = label
        z = percent
        diff_case = pd.DataFrame(x[y]).drop_duplicates([y])
        result = []
        result = pd.DataFrame(result)
        for i in range(len(diff_case)):
            k = np.array(diff_case)[i]
            data_set = x[x[y] == k[0]]
            nrow_nb = data_set.iloc[:, 0].count()
            data_set.index = range(nrow_nb)
            index_id = rd.sample(range(nrow_nb), int(nrow_nb * z))
            result = pd.concat([result, data_set.iloc[index_id, :]], axis=0)
        new_data = pd.Series(result['label']).value_counts()
        new_data = pd.DataFrame(new_data)
        new_data.columns = ['cnt']
        k1 = pd.DataFrame(new_data.index)
        k2 = new_data['cnt']
        new_data = pd.concat([k1, k2], axis=1)
        new_data.columns = ['id', 'cnt']
        max_cnt = max(new_data['cnt'])
        k3 = new_data[new_data['cnt'] == max_cnt]['id']
        result = result[result[y] == k3[0]]
        return result

    def under_sample(self, data_set, label, percent=0.1, q=1):
        # 欠抽样
        # data_set:数据集
        # label:抽样标签
        # percent:抽样占比
        # q:每次抽取是否随机
        # 抽样根据目标列分层,自动将样本数较多的样本按percent抽样,得到目标列样本较多特征的欠抽样数据
        x = data_set
        y = label
        z = percent
        diff_case = pd.DataFrame(pd.Series(x[y]).value_counts())
        diff_case.columns = ['cnt']
        k1 = pd.DataFrame(diff_case.index)
        k2 = diff_case['cnt']
        diff_case = pd.concat([k1, k2], axis=1)
        diff_case.columns = ['id', 'cnt']
        max_cnt = max(diff_case['cnt'])
        k3 = diff_case[diff_case['cnt'] == max_cnt]['id']
        new_data = x[x[y] == k3[0]].sample(frac=z, random_state=q, axis=0)
        return new_data

    def combine_sample(self, data_set, label, number, percent=0.35, q=1):
        # 组合抽样
        # data_set:数据集
        # label:目标列
        # number:计划抽取多类及少类样本和
        # percent:少类样本占比
        # q:每次抽取是否随机
        # 设定总的期待样本数量,及少类样本占比,采取多类样本欠抽样,少类样本过抽样的组合形式
        x = data_set
        y = label
        n = number
        p = percent
        diff_case = pd.DataFrame(pd.Series(x[y]).value_counts())
        diff_case.columns = ['cnt']
        k1 = pd.DataFrame(diff_case.index)
        k2 = diff_case['cnt']
        diff_case = pd.concat([k1, k2], axis=1)
        diff_case.columns = ['id', 'cnt']
        max_cnt = max(diff_case['cnt'])
        k3 = diff_case[diff_case['cnt'] == max_cnt]['id']
        k4 = diff_case[diff_case['cnt'] != max_cnt]['id']
        n1 = p * n
        n2 = n - n1
        fre1 = n2 / float(x[x[y] == k3[0]]['label'].count())
        fre2 = n1 / float(x[x[y] == k4[1]]['label'].count())
        fre3 = ma.modf(fre2)
        new_data1 = x[x[y] == k3[0]].sample(frac=fre1, random_state=q, axis=0)
        new_data2 = x[x[y] == k4[1]].sample(frac=fre3[0], random_state=q, axis=0)
        test_data = pd.DataFrame([])
        if int(fre3[1]) > 0:
            i = 0
            while i < (int(fre3[1])):
                data = x[x[y] == k4[1]]
                test_data = pd.concat([test_data, data], axis=0)
                i += 1
        result = pd.concat([new_data1, new_data2, test_data], axis=0)
        return result

后续使用,只需要复制上述code,存成.py的文件,后续使用的时候:

#加载函数
import sample_s as sa
#这边可以选择你需要的分层抽样、欠抽样、组合抽样的函数
sample = sa.group_sample()
#直接调用函数即可
new_data3 = sample.combine_sample(data_train, 'label', 60000, 0.4)
#将data_train里面的label保持正样本(少类样本)达到0.4的占比下,总数抽取到60000个样本

其实不是很难的一个过程,只是强化自己对python及R语言的书写方式的记忆,谢谢。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏深度学习与计算机视觉

手把手教你如何应用TF-Slim快速实现迁移学习

这是一篇以实践为主的入门文章,目的在于用尽量少的成本组织起来一套可以训练和测试自己的分类任务的代码,其中就会用到迁移学习,TF-Slim库的内容,所以我们分为下...

1.2K80
来自专栏付越的专栏

深度学习入门篇--手把手教你用 TensorFlow 训练模型

最近笔者终于跑通 TensorFlow Object Detection API的ssd_mobilenet_v1 模型,这里记录下如何完整跑通数据准备到模型使...

6.4K20
来自专栏用户2442861的专栏

决策树python sklearn 示例

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haluoluo211/article/d...

71540
来自专栏ATYUN订阅号

保存并加载您的Keras深度学习模型

Keras是一个用于深度学习的简单而强大的Python库。 鉴于深度学习模式可能需要数小时、数天甚至数周的时间来培训,了解如何保存并将其从磁盘中加载是很重要的...

65460
来自专栏PaddlePaddle

【FAQ】模型配置相关问题汇总

导语 我们用13篇推文向您介绍了如何安装、编译和使用PaddlePaddle,您可以点击公众号右下角的历史消息获取相应的使用指南。 ? 在使用指南的最后一部分,...

392100
来自专栏漫漫深度学习路

tensorflow学习笔记(三十一):构建多GPU代码

构建多GPU代码 结构 先构建单GPU代码 写个函数multi_gpu_model(num_gpus)来生成多GPU代码,并将对象保存在collection中 ...

32270
来自专栏Python小屋

Python使用matplotlib绘制三维曲线

本文主要演示如何使用matplotlib绘制三维图形。直接上代码,关键语句配有注释方便理解。 import matplotlib as mpl from mpl...

37030
来自专栏小鹏的专栏

tf API 研读1:tf.nn,tf.layers, tf.contrib概述

        我们在使用tensorflow时,会发现tf.nn,tf.layers, tf.contrib模块有很多功能是重复的,尤其是卷积操作,在使用的时...

43890
来自专栏ATYUN订阅号

使用Tensorflow对象检测在安卓手机上“寻找”皮卡丘

在TensorFlow的许多功能和工具中,隐藏着一个名为TensorFlow对象探测API(TensorFlow Object Detection API)的组...

52350
来自专栏移动开发面面观

PIL学习笔记(一)

16940

扫码关注云+社区

领取腾讯云代金券