在多标签 SMOTE 中实现自定义 Transformer 遇到的问题
def get_tail_label(df: pd.DataFrame, ql=[0.05, 1.]) -> list: """ Find the underrepresented targets. Underrepresented targets are those which are observed less than the median occurence. Targets beyond a quantile limit are filtered. """ irlbl = df.sum(axis=0) irlbl = irlbl[(irlbl > irlbl.quantile(ql[0])) & ((irlbl < irlbl.quantile(ql[1])))] # Filtering irlbl = irlbl.max() / irlbl threshold_irlbl = irlbl.median() tail_label = irlbl[irlbl > threshold_irlbl].index.tolist() return tail_label def get_minority_samples(X: pd.DataFrame, y: pd.DataFrame, ql=[0.05, 1.]): """ return X_sub: pandas.DataFrame, the feature vector minority dataframe y_sub: pandas.DataFrame, the target vector minority dataframe """ tail_labels = get_tail_label(y, ql=ql) index = y[y[tail_labels].any(axis=1)].index.tolist() X_sub = X[X.index.isin(index)].reset_index(drop=True) y_sub = y[y.index.isin(index)].reset_index(drop=True) return X_sub, y_sub def nearest_neighbour(X: pd.DataFrame, neigh) -> list: """ Give index of 10 nearest neighbor of all the instance args X: np.array, array whose nearest neighbor has to find return indices: list of list, index of 5 NN of each element in X """ nbs = NearestNeighbors(n_neighbors=neigh, metric='euclidean', algorithm='brute').fit(X) euclidean, indices = nbs.kneighbors(X) return indices def MLSMOTE(X, y, n_sample, neigh=5): """ Give the augmented data using MLSMOTE algorithm args X: pandas.DataFrame, input vector DataFrame y: pandas.DataFrame, feature vector dataframe n_sample: int, number of newly generated sample return new_X: pandas.DataFrame, augmented feature vector data target: pandas.DataFrame, augmented target vector data """ indices2 = nearest_neighbour(X, neigh=5) n = len(indices2) new_X = np.zeros((n_sample, X.shape[1])) target = np.zeros((n_sample, y.shape[1])) for i in range(n_sample): reference = random.randint(0, n - 1) neighbor = random.choice(list(indices2[reference, 1:])) all_point = indices2[reference] nn_df = y[y.index.isin(all_point)] ser = nn_df.sum(axis=0, skipna=True) target[i] = np.array([1 if val > 0 else 0 for val in ser]) ratio = 0.5 * (1 - ser / ser.sum()) for j in range(neigh): new_X[i, :] = X[all_point[neighbor + j], :] target[i] = target[i] * ratio return new_X, target
内容来源: scikit-learn-contrib/imbalanced-learn