推荐算法

2 篇文章 0 订阅
2 篇文章 0 订阅

推荐算法

实现代码

package Package1;

import java.io.FileNotFoundException;
import java.util.*;

import java.util.Map.Entry;

/**
 * @author Bert Q
 * ClassName : Computation
 * Description 计算相似性评分
 */
public class Computation {

    /**
     * 需要用到的矩阵文件路径
     */
    private static final String OTHER_MATRIX_PATH = "F:\\MyProjects\\XMGL\\resources\\other.txt";
    private static final String TARGET_MATRIX_PATH = "F:\\MyProjects\\XMGL\\resources\\target.txt";
    private static final String SORTED_SIM_PATH = "F:\\MyProjects\\XMGL\\resources\\tempSim.txt";
    private static final String NEIGHBOUR_MATRIX_PATH = "F:\\MyProjects\\XMGL\\resources\\Neighbour.txt";
    private static final String SIM_MATRIX_PATH = "F:\\MyProjects\\XMGL\\resources\\SimMatrix.txt";


    /**
     * 源相似性数组行列数
     */
    private static final int TARGET_MATRIX_ROWS = 1;
    private static final int TARGET_MATRIX_COLS = 1682;
    private static final int OTHER_MATRIX_ROWS = 942;
    private static final int OTHER_MATRIX_COLS = 1682;
    private static final int SORTED_MATRIX_ROWS = TARGET_MATRIX_ROWS;
    private static final int SORTED_MATRIX_COLS = TARGET_MATRIX_COLS;
    private static final int NEIGHBOUR_MATRIX_ROWS = TARGET_MATRIX_ROWS;
    private static final int NEIGHBOUR_MATRIX_COLS = TARGET_MATRIX_COLS;

    /**
     * 需要的最近邻个数
     */
    private static final int NEIGHBOUR_NUMS = 50;

    /**
     * 输出路径
     */
    private static final String RESULT_SIM_OUTPUT_PATH = "F:\\MyProjects\\XMGL\\resources\\Result.txt";
    private static final String RESULT_INDEX_OUTPUT_PATH = "F:\\MyProjects\\XMGL\\resources\\ResultIndex.txt";

    /**
     * 定义无意义的值
     */
    private static final int MEANINGLESS_VALUE = -1000;


    public static void main(String[] args) {
        try {
            //读取文件 获得需要使用的四个矩阵
            int[][] neighbourMatrix = KnnInputOutput.TxtToIntArray(NEIGHBOUR_MATRIX_PATH, NEIGHBOUR_MATRIX_ROWS, OTHER_MATRIX_ROWS);
            double[][] simMatrix = KnnInputOutput.TxtToDouArray(SIM_MATRIX_PATH, SORTED_MATRIX_ROWS, SORTED_MATRIX_COLS);
            double[][] targetMatrix = KnnInputOutput.TxtToDouArray(TARGET_MATRIX_PATH, TARGET_MATRIX_ROWS, TARGET_MATRIX_COLS);
            double[][] otherMatrix = KnnInputOutput.TxtToDouArray(OTHER_MATRIX_PATH, OTHER_MATRIX_ROWS, OTHER_MATRIX_COLS);
            // 获取preRating矩阵
            double[][] preRatingsMatrix = getPreRatingsMatrix(targetMatrix, otherMatrix, simMatrix, neighbourMatrix);
            // 对preRating矩阵进行排序
            List<Entry<Integer, Double>> sortedMatrix = sortMatrix(preRatingsMatrix);
            // 输出排序后的矩阵和下标
            outputSortedMatrixAndNeighbourMatrix(sortedMatrix);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 获取prerating矩阵,其为目标用户对未评分项目的预测评分矩阵
     * 若已有评分,则赋上一个无意义的数(-1000)
     * 否则,计算其预测评分
     *
     * @param targetMatrix 目标用户矩阵
     * @param otherMatrix  其他用户矩阵
     * @param simMatrix    相似性矩阵
     * @param neighbour    相邻矩阵
     * @return 目标用户对未评分项的矩阵
     * @see calcPredictionScore(int i, double[][] targetMatrix, double[][] otherMatrix, double[][] simMatrix, int[][] neighbour)
     */
    public static double[][] getPreRatingsMatrix(double[][] targetMatrix, double[][] otherMatrix, double[][] simMatrix, int[][] neighbour) {

        double[][] preRatings = new double[1][TARGET_MATRIX_COLS];
        for (int i = 0; i < TARGET_MATRIX_COLS; i++) {
            //如果未评分,去评分
            if (targetMatrix[0][i] == 0) {
                preRatings[0][i] = calcPredictionScore(i, targetMatrix, otherMatrix, simMatrix, neighbour);
            } else {
                // 用户已给出评分,则赋上一个无意义的值
                preRatings[0][i] = MEANINGLESS_VALUE;
            }
        }

        return preRatings;
    }

    /**
     * 计算预测评分
     *
     * @param i            该用户对第i的项目的预测
     * @param targetMatrix 目标用户矩阵
     * @param otherMatrix  其他用户矩阵
     * @param simMatrix    相似性矩阵
     * @param neighbour    相邻矩阵
     * @return  计算后得到的评分
     */
    public static double calcPredictionScore(int i, double[][] targetMatrix, double[][] otherMatrix, double[][] simMatrix, int[][] neighbour) {
        double molecule = 0d; // 初始化分子
        double denominator = 0d;// 初始化分母

        double avg_rua = avgInMatrixRowWithout0(targetMatrix, 1);// 计算目标用户的平均评分 (公式最左边Rua)

        for (int j = 0; j < NEIGHBOUR_NUMS; j++) {// 取相邻矩阵的前N个进行预测

            int currentNeighbour = neighbour[0][j]; // 取得当前相邻矩阵的角标
            double sim = simMatrix[0][currentNeighbour];// 计算与相邻矩阵的相似性
            // 如果sim为无意义的值或者相似性最高的用户对其也未作出评分,跳过此次计算。
            if (sim == MEANINGLESS_VALUE || otherMatrix[currentNeighbour][i] == 0) {
                continue;
            }
            //计算其他用户对第i个项目的评分减去其他用户的平均评分
            double r_ret = otherMatrix[currentNeighbour][i] - avgInMatrixRowWithout0(otherMatrix, currentNeighbour + 1);

            molecule += sim * r_ret;
            denominator += Math.abs(sim);

        }
        // 如果分母为0时,直接返回无意义的数,否则根据公式计算返回结果
        return denominator == 0 ? MEANINGLESS_VALUE : avg_rua + (molecule / denominator);
    }


    /**
     * 计算某矩阵某行的平均值,去除0
     *
     * @param matrix 被计算的矩阵
     * @param row    需要被计算平均值的行
     * @return 平均值
     */
    public static double avgInMatrixRowWithout0(double[][] matrix, int row) {
        double sum = 0;
        int divideCount = 0;
        for (int j = 0; j < matrix[row - 1].length; j++) {
            if (matrix[row - 1][j] == 0) {
                continue;
            }
            sum += matrix[row - 1][j];
            divideCount++;
        }
        return sum / divideCount;
    }

    /**
     * 对矩阵进行排序
     *
     * @param matrix 要被排序的矩阵
     * @return 排序后的list集合
     */
    public static List<Map.Entry<Integer, Double>> sortMatrix(double[][] matrix) {
        Map<Integer, Double> resultMap = new HashMap<Integer, Double>();

        for (int i = 0; i < matrix[0].length; i++) {
            resultMap.put(i, matrix[0][i]);
        }

        List<Map.Entry<Integer, Double>> sortedList = new ArrayList<Map.Entry<Integer, Double>>(resultMap.entrySet());
        Collections.sort(sortedList, new Comparator<Map.Entry<Integer, Double>>() {
            public int compare(Entry<Integer, Double> o1,
                               Entry<Integer, Double> o2) {
                return o2.getValue().compareTo(o1.getValue());
            }
        });


        return sortedList;
    }

    /**
     * 输出排序后的矩阵,和矩阵下标
     *
     * @param sortedList 使用sortMatrix方法进行排序后的集合
     * @see List<Map.Entry<Integer, Double>> sortMatrix(double[][] matrix) 方法
     */
    public static void outputSortedMatrixAndNeighbourMatrix(List<Map.Entry<Integer, Double>> sortedList) {
        double[][] sortedMatrix = new double[SORTED_MATRIX_ROWS][SORTED_MATRIX_COLS];
        int[][] neighborMatrx = new int[NEIGHBOUR_MATRIX_ROWS][NEIGHBOUR_MATRIX_COLS];
        for (int i = 0; i < sortedList.size(); i++) {
            Entry<Integer, Double> entry = sortedList.get(i);
            neighborMatrx[0][i] = entry.getKey();
            sortedMatrix[0][i] = entry.getValue();
        }
        // 输出排序后的矩阵
        KnnInputOutput.douArrayToTxt(RESULT_SIM_OUTPUT_PATH, sortedMatrix, SORTED_MATRIX_ROWS, SORTED_MATRIX_COLS);
        // 输出排序后的矩阵的下标
        KnnInputOutput.intArrayToTxt(RESULT_INDEX_OUTPUT_PATH, neighborMatrx, NEIGHBOUR_MATRIX_ROWS, NEIGHBOUR_MATRIX_COLS);
    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值