我使用 SGD 算法实现了矩阵分解,但是当我运行它时,我经常在预测矩阵中得到 NaN。当我在一个非常小的 (6 x 7) 矩阵上运行算法时,错误出现的次数很少。当我转移到电影镜头数据集时,每次运行算法时我都会在所有单元格中得到错误。错误仅在某些单元格中消失的唯一时间是当我将优化步骤(迭代次数)设置为 1 时。
private static Matrix matrixFactorizationLarge (Matrix realRatingMatrix, Matrix factor_1, Matrix factor_2)
{
int features = (int) factor_1.getColumnCount();
double learningRate = 0.02;
double regularization = 0.02;
int optimizationSteps = 10;
Matrix predictedRatingMatrix = SparseMatrix.Factory.zeros(realRatingMatrix.getRowCount(), realRatingMatrix.getColumnCount());
for (int step = 0; step < optimizationSteps; step++)
{
for (int row = 0; row < predictedRatingMatrix.getRowCount(); row++)
{
for (int col = 0; col < predictedRatingMatrix.getColumnCount(); col++)
{
if (realRatingMatrix.getAsInt(row, col) > 0)
{
Matrix vector_1 = getRow(factor_1, row);
Matrix vector_2 = getColumn(factor_2, col);
predictedRatingMatrix.setAsDouble( ( Math.floor ( dotProduct(vector_1, vector_2) * 100 ) ) / 100, row, col);
for (int f = 0; f < features; f++)
{
factor_1.setAsDouble( ( Math.floor ( ( factor_1.getAsDouble(row, f) + ( learningRate * ( ( calculateDerivative(realRatingMatrix.getAsDouble(row, col), predictedRatingMatrix.getAsDouble(row, col), factor_2.getAsDouble(f, col) ) ) - ( regularization * factor_1.getAsDouble(row, f) ) ) ) ) * 100 ) / 100), row, f);
factor_2.setAsDouble( ( Math.floor ( ( factor_2.getAsDouble(f, col) + ( learningRate * ( ( calculateDerivative(realRatingMatrix.getAsDouble(row, col), predictedRatingMatrix.getAsDouble(row, col), factor_1.getAsDouble(row, f) ) ) - ( regularization * factor_2.getAsDouble(f, col) ) ) ) ) * 100 ) / 100), f, col);
}
}
}
}
}
return predictedRatingMatrix;
}
相关方法如下:
private static double dotProduct (Matrix vector_A, Matrix vector_B)
{
double dotProduct = 0.0;
for (int index = 0; index < vector_A.getColumnCount(); index++)
{
dotProduct = dotProduct + ( vector_A.getAsDouble(0, index) * vector_B.getAsDouble(0, index) );
}
return dotProduct;
}
private static double errorOfDotProduct (double original, double dotProduct)
{
double error = 0.0;
error = Math.pow( ( original - dotProduct ), 2 );
return error;
}
private static double calculateDerivative(double realValue, double predictedValue, double value)
{
return ( 2 * (realValue - predictedValue) * (value) );
}
private static double calculateRMSE (Matrix realRatingMatrix, Matrix predictedRatingMatrix)
{
double rmse = 0.0;
double summation = 0.0;
for (int row = 0; row < realRatingMatrix.getRowCount(); row++)
{
for (int col = 0; col < realRatingMatrix.getColumnCount(); col++)
{
if (realRatingMatrix.getAsDouble(row, col) != 0)
{
summation = summation + errorOfDotProduct(realRatingMatrix.getAsDouble(row, col), predictedRatingMatrix.getAsDouble(row, col));
}
}
}
rmse = Math.sqrt(summation);
return rmse;
}
private static Matrix csvToMatrixLarge (File csvFile)
{
Scanner inputStream;
Matrix realRatingMatrix = SparseMatrix.Factory.zeros(610, 17000);
// Matrix realRatingMatrix = SparseMatrix.Factory.zeros(6, 7);
try
{
inputStream = new Scanner(csvFile);
while (inputStream.hasNext()) {
String ln = inputStream.next();
String[] values = ln.split(",");
double rating = Double.parseDouble(values[2]);
int row = Integer.parseInt(values[0])-1;
int col = Integer.parseInt(values[1])-1;
if (col < 1000)
{
realRatingMatrix.setAsDouble(rating, row, col);
}
}
inputStream.close();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
return realRatingMatrix;
}
private static Matrix createFactorLarge (long rows, long features)
{
Matrix factor = DenseMatrix.Factory.zeros(rows, features);
return factor;
}
private static void fillInMatrixLarge (Matrix matrix)
{
for (int row = 0; row < matrix.getRowCount() ; row++)
{
for (int col = 0; col < matrix.getColumnCount(); col++)
{
double random = ThreadLocalRandom.current().nextDouble(5.1);
matrix.setAsDouble( (Math.floor (random * 10 ) / 10), row, col);
}
}
// return matrix;
}
private static Matrix getRow (Matrix matrix, int rowOfIntresst)
{
Matrix row = Matrix.Factory.zeros(1, matrix.getColumnCount());
for (int col = 0; col < matrix.getColumnCount(); col++)
{
row.setAsDouble(matrix.getAsDouble(rowOfIntresst, col), 0, col);
}
return row;
}
private static Matrix getColumn (Matrix matrix, int colOfInteresst)
{
Matrix column = Matrix.Factory.zeros(1, matrix.getRowCount());
for (int index = 0; index < matrix.getRowCount(); index++)
{
column.setAsDouble(matrix.getAsDouble(index, colOfInteresst), 0, index); //column[row] = matrix[row][colOfInteresst];
}
return column;
}
是什么导致错误,因为我没有在算法中除以零?我该如何解决?
PS我正在使用通用矩阵库包