ADASYN(Adaptive Synthetic Sampling)是一种基于 SMOTE 的过采样办法,它经过核算每个少量类样本周围的大都类样本份额,决议需求发生的新样本数量。ADASYN 能够更好地习惯不同的数据集,由于它会为那些与大都类更接近的少量类样本发生更多的新样本,而为那些与大都类更远的少量类样本发生较少的新样本。这种办法能够帮助防止发生噪声样本,并提高分类器的性能。
下面是 ADASYN 办法的详细流程:
- 关于每个少量类样本,核算它周围大都类样本的份额 p;
- 关于每个少量类样本,核算需求发生的新样本数量 n = p * k,其间 k 是一个可调参数,用于控制新样本的数量;
- 关于每个少量类样本,从它的 k 个最近邻的大都类样本中随机挑选 n 个样本,并将它们刺进到少量类样本和其 k 个最近邻之间。
下面是 ADASYN 的 Python 代码完成:
import numpy as np
from sklearn.neighbors import NearestNeighbors
def ADASYN(X, y, k=5, ratio=0.5):
"""
ADASYN: Adaptive Synthetic Sampling
"""
# 核算每个少量类样本周围大都类样本的数量
neigh = NearestNeighbors(n_neighbors=k+1)
neigh.fit(X[y == 1])
distances, indices = neigh.kneighbors()
n_samples, n_features = X.shape
synthetic_X = []
synthetic_y = []
for i in range(len(indices)):
# 核算需求发生的新样本数量
n = int(round(ratio * indices[i].shape[0]))
if n == 0:
continue
# 关于每个少量类样本,随机挑选 n 个样本,并刺进到样本之间
for j in range(n):
nn = np.random.randint(1, indices[i].shape[0])
dif = X[indices[i][nn]] - X[indices[i][0]]
gap = np.random.random()
synthetic = X[indices[i][0]] + gap * dif
synthetic_X.append(synthetic)
synthetic_y.append(1)
synthetic_X = np.array(synthetic_X)
synthetic_y = np.array(synthetic_y)
# 将生成的新样本和原始样本兼并成新的练习集
X = np.vstack((X, synthetic_X))
y = np.hstack((y, synthetic_y))
return X, y
上面的代码中,输入 X 是练习数据的特征矩阵,y 是练习数据的标签,k 是指定的 k 值,ratio 是新样本占比的参数。函数首先核算每个少量类样本周围大都类样本的数量,然后随机从大都类样本中挑选必定数量的样本,刺进到少量类样本和其 k 个最近邻之间,生成新的组成样本。最终,将生成的新样本和原始样本兼并成新的练习集回来。
需求留意的是,ADASYN 办法在生成新样本时可能会发生重叠的样本,因此需求在生成后去除重复的样本。
下面是一个简单的示例:
from collections import Counter
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
# 生成一个二分类样本不平衡的数据集
X, y = make_classification(n_classes=2, class_sep=2,
weights=[0.1, 0.9], n_informative=3,
n_redundant=1, flip_y=0, n_features=20,
n_clusters_per_class=1, n_samples=1000,
random_state=10)
# 原始数据会集少量类样本的数量
print('Original dataset shape %s' % Counter(y))
# 划分练习集和测验集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=10)
# 运用 ADASYN 过采样办法平衡练习集
X_resampled, y_resampled = ADASYN(X_train, y_train)
# 平衡后的数据会集少量类样本的数量
print('Resampled dataset shape %s' % Counter(y_resampled))
# 练习模型
clf = LogisticRegression(random_state=10)
clf.fit(X_resampled, y_resampled)
# 在测验集上进行猜测并评价性能
y_pred = clf.predict(X_test)
print(classification_report(y_test, y_pred))
在这个示例中,咱们运用了 make_classification() 函数生成一个二分类样本不平衡的数据集,并划分出练习集和测验集。然后,咱们运用 ADASYN 过采样办法平衡练习集,并练习逻辑回归模型进行分类。最终,咱们在测验集上进行猜测并评价模型性能。
上面的代码中运用的 ADASYN() 函数并不是 sklearn 中供给的函数,这里咱们自己完成一下 ADASYN 过采样算法。
import numpy as np
from sklearn.neighbors import NearestNeighbors
def ADASYN(X, y, k=5, ratio=1):
"""
ADASYN 过采样算法完成
参数:
X: 原始特征矩阵
y: 原始标签向量
k: 挑选 k 个最近邻样本
ratio: 生成新样本与原样本份额
回来值:
new_X: 组成新的特征矩阵
new_y: 组成新的标签向量
"""
# 统计少量类样本的数量和大都类样本的数量
minority_num = sum(y == 1)
majority_num = sum(y == 0)
# 核算需求生成的新样本数量
new_sample_num = int((minority_num * ratio) - minority_num)
# 假如新样本数量为 0,则回来原始数据集
if new_sample_num == 0:
return X, y
# 核算每个少量类样本需求生成的新样本数量
num_neighbors = np.zeros(minority_num)
for i in range(minority_num):
# 核算少量类样本 i 的 k 个最近邻样本
nn = NearestNeighbors(n_neighbors=k+1)
nn.fit(X[y == 1])
distances, indices = nn.kneighbors(X[y == 1][i].reshape(1, -1))
# 核算少量类样本 i 和其 k 个最近邻样本中属于大都类的样本数量
num_neighbors[i] = sum(y[y == 1][indices[0, 1:]] == 0)
# 核算少量类样本 i 生成新样本的份额,即生成 num_synthetic 样本
# 需求从其 k 个最近邻样本中挑选 num_synthetic * (num_neighbors[i] / sum(num_neighbors)) 个样本
synthetic_ratios = num_neighbors / sum(num_neighbors)
num_synthetic = np.round(synthetic_ratios * new_sample_num).astype(int)
# 对每个少量类样本 i,依据其 k 个最近邻样本生成 num_synthetic 个新样本
new_X = []
new_y = []
for i in range(minority_num):
nn = NearestNeighbors(n_neighbors=k+1)
nn.fit(X[y == 1])
distances, indices = nn.kneighbors(X[y == 1][i].reshape(1, -1))
# 生成 num_synthetic[i] 个新样本
for j in range(num_synthetic[i]):
# 随机挑选一个少量类样本的 k 个最近邻样本
nn_index = np.random.randint(1, k+1)
# 核算组成样本的特征值
dif = X[y == 1][indices[0, nn_index]] - X[y == 1][i]
gap = np.random.rand(1, X.shape[1])
new_X.append(X[y == 1][i] + gap * dif)
new_y.append(1)
# 将新生成的新样本和原始数据集兼并,回来组成的新特征矩阵和新标签向量
new_X = np.vstack([X, np.array(new_X).reshape(-1, X.shape[1])])
new_y = np.hstack([y, np.array(new_y)])
return new_X, new_y
以上是 Python 代码完成 ADASYN 过采样算法的过程。经过统计少量类样本的数量和大都类样本的数量,核算需求生成的新样本数量,并依据每个少量类样本的 k 个最近邻样本生成新样本,最终将新生成的样本和原始数据集兼并,即可得到组成的新特征矩阵和新标签向量。