机器学习(四) 下采样和上采样

查看数据样本

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

%matplotlib inline

data = pd.read_csv("./data/creditcard.csv")
data.head()

在这里插入图片描述

这个数据,并不是最原始数据,而是通过降维操作把数据进行特征压缩。我们可以根据这些特征进行建模。

这些数据有一列class,用来标注是否正常,0表示正常,1表示异常。

这是经典的二分类问题。

首先查看当前数据的正负样本的比例:

count_classes = pd.value_counts(data['Class'], sort=True).sort_index()
count_classes.plot(kind='bar') # 用pandas也可以花一些简单的图
plt.title("Fraud class histogram")
plt.xlabel("Class")
plt.ylabel("Frequency")

在这里插入图片描述
可以看出0样本占了大多数, 1样本占了很少的数量。

因此两个数据量并不均衡,如何进行调整?

1. 下采样

例如0样本数据量大约28万,1样本数据量大约几百个。可以让0样本采集几百个,跟1样本的数量同样少。

2. 上采样

生成1样本数据,与0样本的数据量一样。

3. 特征分布

从数据中可以看到,Amount列的数据与其他特征的数据值差异较大,一些算法会误以为数据大则重要程度高,所以为了使得每个特征的重要程度是相当的,需要对Amount的数据进行归一化。

可以通过sklearn进行处理:

from sklearn.preprocessing import StandardScaler

data['normAmount'] = StandardScaler().fit_transform(data['Amount'].values.reshape(-1, 1)) # 对数据进行标准化,reshape相当于对矩阵进行行列的变换,成为新的特征['normAmount'],加到原始数据
data = data.drop(['Time', 'Amount'], axis=1) # 将Time和Amount列删掉
data.head()

reshape相当于对矩阵进行行列的变换,例如矩阵 A 3 × 6 A_{3\times6} A3×6经过A.reshape(-1, 2)就会自动变成 B 9 × 2 B_{9\times2} B9×2,数据总量不变。调整后的数据如下:
在这里插入图片描述

使用下采样进行调整

X = data.loc[:, data.columns.values != ["Class"]] # 获取特征数据
y = data.loc[:, data.columns.values == ["Class"]] # 获取标签

#print(X.head())
#print(y.head())
number_records_fraud = len(y[y["Class"]==1])# 标签为1的样本数量,异常样本的数量
print(len(y[y["Class"]==1])) 
print(len(y[y["Class"]==0])) # 标签为0的样本数量,正常样本的数量

fraud_indices = y[y.Class==1].index # 获取标签为1的样本的索引
normal_indices = y[y.Class==0].index # 获取标签为0的样本的索引
# print(normal_indices)

random_normal_indices = np.random.choice(normal_indices, number_records_fraud, replace=False) # 随机从class=0的样本中拿number_records_fraud个数据
random_normal_indices = np.array(random_normal_indices)

# 将两种index合并到一起,下采样
under_sample_indices = np.concatenate([fraud_indices, random_normal_indices])
under_sample_data = data.iloc[under_sample_indices, :]

print(len(under_sample_data[under_sample_data.Class==0])) # 492
print(len(under_sample_data[under_sample_data.Class==1])) # 492

这样就通过下采样的方式将数据分布均衡,代价就是很多数据没有利用。

交叉验证

一般情况下,当我们达到数据时,会将数据80%分割为训练集,数据20%分割为测试集。还可以将训练集继续平均分割成3份,分别是训练集、验证集,这里用A、B、C表示。我们可以通过交叉验证的方式来调整参数,通过验证集当前模型参数是好还是不好。第一次可以用A+B进行训练,用C进行验证;第二次用A+C进行训练,用B进行验证;第三次用B+C进行训练,用A进行验证。

这么做主要是为了防止某一部分的数据比较简单,导致模型效果比较高。

模型的评估标准

假设有1000个人,其中990个人正常,有10个人患有癌症,模型旨在预测哪些人是患有癌症的。
如果模型预测1000个人中都是正常的,没有癌症患者,那么可以说模型的精度是 990 1000 = 0.99 \frac{990}{1000}=0.99 1000990=0.99。虽然精度很高,但是都是正样本,没有负样本,模型是无用的,因为一个患者都没有找到。因此无法用精度来评估模型,而是使用recall召回率来评估。

上采样SMOTE算法

在这里插入图片描述

  1. 对于少数类中每一个样本x,以欧氏距离为标准计算它到少数类样本集中所有样本的距离,得到其k近邻
  2. 根据样本不平衡比例设置一个采样比例以确定采样倍率N,对于每一个少数类样本x,从其k近邻中随机选择若干个样本,假设选择的近邻为xn
  3. 对于每一个随机选出的近邻xn,分别与原样本按照如下的公式构建新的样本。

x n e w = x + r a n d ( 0 , 1 ) × ( x ~ − x ) x_{new}=x+ rand(0,1)\times(\tilde{x} -x) xnew=x+rand(0,1)×(x~x)

import pandas as pd
from imblearn.over_sampling import SMOTE

features_train, feature_test, labels_train, labels_test = train_test_split(X, y, test_size=0.2, random_state = 0) # test_size表示切分比例,20%的数据作为测试集;random_state表示让每一次随机出的样本都一致
oversampler = SMOTE(random_state=0)
os_features,os_labels=oversampler.fit_sample(features_train, labels_train)
len(os_labels[os_labels==1])

这样就生成了很多数据。

  • 8
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值