SMOTE算法的Java实现

/```
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++;
        }
    }
}

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容