python 下采样和上采样[通俗易懂]
前言
由于工作数据量较大,训练模型很少直接单机python,一般都采用SparkML,最近把SparkML的工作使用python简单的写了一下,先写个上下采样,最终目的是为了让正负样本达到均衡(有人问:正负样本必须是1:1吗?1:1效果就一定最好吗?答:不一定)
数据准备
共20条数据,正样本1共有5条,负样本0共有15条。
基础知识准备
- 如何获取dataframe的行数 pandas.DataFrame.shape 返回数据帧的形状
df.shape[0] 返回行数
de.shape[1] 返回列数
只听到从架构师办公室传来架构君的声音: 道别来、浑是不关心,东堂桂。 有谁来对上联或下联?
或者直接使用
此代码由Java架构师必看网-架构君整理
len(df)
当然如果要统计每个字段不同类别的数量,可以类似于SQL中的count(*) group by 操作
df.groupby('字段名').size()
- 创建一个数据结构和之前一致,但空的dataframe
方法1:
此代码由Java架构师必看网-架构君整理
df = df.iloc[0:0].copy()
方法2:
df.drop(df.index, inplace=True)
方法3:
df_1 = df.drop(range(len(df)),axis=0)
读取数据和获取正负样本数量
import pandas as pd
data = pd.read_csv('./test.csv')
# 获取正样本的数量
z = data[data['label'] == 1]
# 获取负样本的数量
f = data[data['label'] == 0]
上采样
就是不断复制样本少的数据达到和样本多的数据平衡
frac = int(len(f) / len(z))
# 创建一个数据结构和之前一致,但空的dataframe
zcopy = z.iloc[0:0].copy()
# 上采样就是复制少量的样本直到和多量的达到平衡
for i in range(frac):
if i != frac:
zcopy = zcopy.append(z)
sample_data = pd.concat([zcopy,f])
查看采样的结果:
下采样
下采样就是从多量的样本中抽取一部分数据直到和少量的样本达到平衡
- 利用dataframe的sample方法
frac = float(len(z) / len(f))
# 下采样就是从多量的样本中抽取一部分数据直到和少量的样本达到平衡
sample_data = pd.concat([f.sample(frac=frac),z])
结果:
2. 利用np.random.choice() (个人感觉有点繁琐,不推荐)
import numpy as np
# 得到所有正样本的索引
z_index = np.array(z.index)
# 下采样就是从多量的样本中抽取一部分数据直到和少量的样本达到平衡,并取其索引
random_f_index = np.random.choice(f.index,len(z),replace = False)