/```
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
//File file = new File("D:/iris2.txt");
//D:\GD\WC\part-r-00000
public class smote {
public void test(String pathname) throws Exception {
int num_k = 8; // 参数一,SMOTE过程中使用的k近邻
int num_feature = 4; // 参数二,特征的个数
int num_rate = 5; // 参数三,过采样倍率
double[][] min_orignal = new double[100][num_feature]; // 生成指定列数的数组
int len = 0; // 计数一共有多少个少数类样本点
// String pathname = "D:\GD\WC\part-r-00000"; //
// 绝对路径或相对路径都可以,写入文件时演示相对路径,读取以上路径的input.txt文件
// 防止文件建立或读取失败,用catch捕捉错误并打印,也可以throw;
// 不关闭文件会导致资源的泄露,读写文件都同理
// Java7的try-with-resources可以优雅关闭文件,异常时自动关闭文件;详细解读https://stackoverflow.com/a/12665271
try (FileReader reader = new FileReader(pathname); BufferedReader br = new BufferedReader(reader) // 建立一个对象,它把文件内容转成计算机能读懂的语言
) {
String line;
while ((line = br.readLine()) != null) {
// 一次读入一行数据
// System.out.println(line);
String[] words = line.split(",");
for (int j = 0; j < words.length; j++) {
min_orignal[len][j] = Double.parseDouble(words[j]);
}
len++;
}
} catch (IOException e) {
e.printStackTrace();
}
// 完成读文件,所有少数类样本存储入min_orignal
// 下面求近邻矩阵
double tmp;
double[][] dis_matrix = new double[len][len]; // 距离矩阵,用于求取最近邻
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
tmp = 0;
for (int k = 0; k < num_feature; k++) {
// tmp = tmp + Math.pow(min_orignal[i][k]-min_orignal[j][k], 2);
// tmp = tmp + Math.abs(min_orignal[i][k]-min_orignal[j][k]);
double a = min_orignal[i][k];
double b = min_orignal[j][k];
tmp = tmp + Math.abs(a - b);
}
// dis_matrix[i][j] = Math.sqrt(tmp);
dis_matrix[i][j] = tmp;
}
}
// 下面求n个最近邻的下标,得到k最近邻矩阵nig_addr,按照距离升序
int locat = 0;
double min;
int[][] nig_addr = new int[len][num_k]; // nig_addr存储近邻位置,用于存储位置
int[][] nig_addr2 = new int[len][num_k]; // 考虑到方便smote过程,设置了冗余的nig_addr矩阵,用于标记是否被索引
for (int i = 0; i < len; i++) {
for (int k = 0; k < num_k; k++) { // 查找k次最小值及下标
min = Double.POSITIVE_INFINITY; // 初始值设为无限大
for (int j = 0; j < len; j++) { // 查找最小值及下标
if (dis_matrix[i][j] < min && dis_matrix[i][j] != 0) {
min = dis_matrix[i][j];
locat = j;
}
}
nig_addr2[i][k] = nig_addr[i][k] = locat;
dis_matrix[i][locat] = 0; // 每找到一个非0的最小值,设为0,下一次遍历寻找次小值
}
}
// 下面进行smote过程
Random random = new Random();// 默认构造方法
double[][] min_created = new double[len * num_rate][num_feature]; // 生成样本矩阵
int index = 0;
for (int i = 0; i < len; i++) {
for (int j = 0; j < num_rate; j++) {
int p1 = i;
int p2; // 指示是哪两个两个样本点
int p2_index1 = random.nextInt(num_k);
while (nig_addr2[i][p2_index1] == len) { // 这里避免重复,进行一个while判断,直到随机数取到没取过的位置
p2_index1 = random.nextInt(num_k); // 得到第二个样本点的一层索引,即在nig_addr的索引
}
nig_addr2[i][p2_index1] = len; // 设置为len避免重复,因为nig_addr最大只能取到len-1的值
p2 = nig_addr[i][p2_index1]; // 第二个样本点
System.out.print(p2_index1 + " ");
System.out.println(p1 + " " + p2);
for (int k = 0; k < num_feature; k++) {
//if (index == 100)
//break;
// System.out.print(min_orignal[p1][k] + " "+ min_orignal[p2][k]);
min_created[index][k] = (min_orignal[p1][k] > min_orignal[p2][k])
? (Math.random() * (min_orignal[p1][k] - min_orignal[p2][k]) + min_orignal[p2][k])
: (Math.random() * (min_orignal[p2][k] - min_orignal[p1][k]) + min_orignal[p1][k]);
System.out.print("/" + min_created[index][k]);
}
index++;
}
}
}
}