Contrast algorithm

/********************************************************
 * c_NMF.cpp: C++ implements on NMF
 * Author: Jamie Zhu <jimzhu@GitHub>
 * Created: 2014/5/6
 * Last updated: 2014/5/7
********************************************************/

#include <iostream>
#include <cstring>
#include <cmath>
#include <limits> 
#include "c_NMF.h"
using namespace std;

#define EPS numeric_limits<double>::epsilon()


void c_NMF(double *removedData, int numUser, int numService, int dim, 
    double lmda, int maxIter, double *Udata, double *Sdata)
{    
    // --- transfer the 1D pointer to 2D array pointer
    double **removedMatrix = vector2Matrix(removedData, numUser, numService);
    double **U = vector2Matrix(Udata, numUser, dim);
    double **S = vector2Matrix(Sdata, numService, dim);
    
    // --- create a set of temporal matries
    double **predMatrix = createMatrix(numUser, numService);

    // --- iterate by standard NMF algorithm
    int iter, i, j, k; 
    for (iter = 0; iter < maxIter; iter++) {
        // --- update predMatrix
        U_dot_S(removedMatrix, U, S, numUser, numService, dim, predMatrix);

        // update U
        for (i = 0; i < numUser; i++) {
            for (k = 0; k < dim; k++) {
                double up = 0;
                double down = 0;
                for (j = 0; j < numService; j++) {
                    if (removedMatrix != 0) {
                        up += removedMatrix[i][j] * S[j][k];
                        down += predMatrix[i][j] * S[j][k];
                    }
                }
                down += U[i][k] * lmda;
                if (down == 0) down += EPS;        
                U[i][k] = U[i][k] * up / down;
            }
        }
        
        // update predMatrix
        U_dot_S(removedMatrix, U, S, numUser, numService, dim, predMatrix);

        // update S
        for (j = 0; j < numService; j++) {
            for (k = 0; k < dim; k++) {
                DOUBLE UP = 0;
                double down = 0;
                for (i = 0; i < numUser; i++) {
                    if (removedMatrix[i][j] > 0) {
                        up += removedMatrix[i][j] * U[i][k];
                        down += predMatrix[i][j] * U[i][k];
                    }
                }
                down += S[j][k] * lmda;
                if (down == 0) down += EPS;
                S[j][k] = S[j][k] * up / down;
            }
        }
        
        // Uncomment this line for testing
        // cout << "Loss: " << loss(U, S, removedMatrix, predMatrix, lmda, numUser, numService, dim) << endl;
    }

    delete2DMatrix(predMatrix);
    delete ((char*) U);
    delete ((char*) S);
    delete ((char*) removedMatrix);
}


double loss(double **U, double **S, double **removedMatrix, double **predMatrix, 
    double lmda, int numUser, int numService, int dim)
{
    int i, j, k;
    double loss = 0;

    // cost
    for (i = 0; i < numUser; i++) {
        for (j = 0; j < numService; j++) {
            if (removedMatrix[i][j] > 0) {
                loss + = 0.5* (removedMatrix [i] [j] - predMatrix [i] [j])
                             * (removedMatrix [i] [j] - predMatrix [i] [j]);    
            } 
        } 
    } 

    // regularization 
    for (k = 0 ; k <dim; k ++ ) {
         for (i = 0 ; i <numUser; i ++ ) { 
            loss + = 0.5 * lmda * U [i] [k] * U [i ] [k]; 
        } 
        For (j = 0 ; j <vice bottoms; j ++ ) { 
            loss + = 0.5 * lmda * S [j] [k] * S [j] [k]; 
        }
    }

    return loss;
}


void U_dot_S(double **removedMatrix, double **U, double **S, int numUser, 
        int numService, int dim, double **predMatrix)
{
    int i, j;
    for (i = 0; i < numUser; i++) {
        for (j = 0; j < numService; j++) {
            if (removedMatrix[i][j] > 0) {
                predMatrix[i][j] = dotProduct(U[i], S[j], dim);  
            }
        }
    }
}


double **vector2Matrix(double *vector, int row, int col)  
{
    double **matrix = new double *[row];
    if (!matrix) {
        cout << "Memory allocation failed in vector2Matrix." << endl;
        return NULL;
    }

    int i;
    for (i = 0; i < row; i++) {
        matrix[i] = vector + i * col;  
    }
    return matrix;
}


double dotProduct(double *vec1, double *vec2, int len)  
{
    double product = 0;
    int i;
    for (i = 0; i < len; i++) {
        product += vec1[i] * vec2[i];
    }
    return product;
}


double **createMatrix(int row, int col) 
{
    double **matrix = new double *[row];
    matrix[0] = new double[row * col];
    memset(matrix[0], 0, row * col * sizeof(double)); // Initialization
    int i;
    for (i = 1; i < row; i++) {
        matrix[i] = matrix[i - 1] + col;
    }
    return matrix;
}


void delete2DMatrix(double **ptr) {
    delete ptr[0];
    delete ptr;
}


void transpose(double **matrix, double **matrix_T, int row, int col) 
{
    int i, j;
    for (i = 0; i < row; i++) {
        for (j = 0; j < col; j++) {
            matrix_T[j][i] = matrix[i][j];
        }
    }
}

 

/********************************************************
 * c_NMF.cpp: C++ implements on NMF
 * Author: Jamie Zhu <jimzhu@GitHub>
 * Created: 2014/5/6
 * Last updated: 2014/5/7
********************************************************/

#include <iostream>
#include <cstring>
#include <cmath>
#include <limits>
#include "c_ourNMF.h"
using namespace std;

#define EPS numeric_limits<double>::epsilon()


void c_ourNMF(double *removedData,double *filledData, int numUser, int numService, int dim,
    double lmda, int maxIter, double *Udata, double *Sdata,double weight)
{
    // --- transfer the 1D pointer to 2D array pointer
    double **removedMatrix = vector2Matrix(removedData, numUser, numService);
    double **filledMatrix = vector2Matrix(filledData, numUser, numService);
    double **U = vector2Matrix(Udata, numUser, dim);
    double **S = vector2Matrix(Sdata, numService, dim);

    // --- create a set of temporal matries
    double **predMatrix = createMatrix(numUser, numService);

    // --- iterate by standard NMF algorithm
    int iter, i, j, k;
    for (iter = 0; iter < maxIter; iter++) {
        // --- update predMatrix
        U_dot_S(filledMatrix, U, S, numUser, numService, dim, predMatrix);

        // update U
        for (i = 0; i < numUser; i++) {
            for (k = 0; k < dim; k++) {
                double up = 0;
                double down = 0;
                for (j = 0; j < numService; j++) {
                    if (removedMatrix[i][j] > 0) {
                        up += removedMatrix[i][j] * S[j][k] ;
                        down += predMatrix[i][j] * S[j][k];
                    }
                    if (removedMatrix[i][j]==0 && filledMatrix[i][j] >0){
                        up += filledMatrix[i][j] * S[j][k] * weight;
                        down += predMatrix[i][j] * S[j][k] * weight;
                    }
                }
                down += U[i][k] * lmda;
                if (down == 0) down += EPS;
                U[i][k] = U[i][k] * up / down;
            }
        }


        // update predMatrix
        U_dot_S(filledMatrix, U, S, numUser, numService, dim, predMatrix);
        // update S
        for (j = 0; j < numService; j++) {
            for (k = 0; k < dim; k++) {
                double up = 0;
                double down = 0;
                for (i = 0; i < numUser; i++) {
                    if (removedMatrix[i][j] > 0) {
                        up += removedMatrix[i][j] * U[i][k];
                        down += predMatrix[i][j] * U[i][k];
                    }
                    if (removedMatrix[i][j] == 0 && filledMatrix[i][j] >0){
                        up += filledMatrix[i][j] * U[i][k] * weight;
                        down += predMatrix[i][j] * U[i][k] * weight;
                    }
                }
                down += S[j][k] * lmda;
                if (down == 0) down += EPS;
                S[j][k] = S[j][k] * up / down;
            }
        }
        // Uncomment this line for testing
        // cout << "Loss: " << loss(U, S, removedMatrix, predMatrix, lmda, numUser, numService, dim) << endl;
    }

    delete2DMatrix(predMatrix);
    delete ((char*) U);
    delete ((char*) S);
    delete ((char*) removedMatrix);
    delete ((char*) filledMatrix);
}


double loss(double **U, double **S, double **removedMatrix, double **filledMatrix, double **predMatrix,
    double lmda, int numUser, int numService, int dim,double weight)
{
    int i, j, k;
    double loss = 0;

    // cost
    for (i = 0; i < numUser; i++) {
        for (j = 0; j < numService; j++) {
            if (removedMatrix[i][j] > 0) {
                loss += 0.5 * (removedMatrix[i][j] - predMatrix[i][j]) * (removedMatrix[i][j] - predMatrix[i][j]);
            }
            if (filledMatrix[i][j] >0 && removedMatrix[i][j] == 0){
                loss += 0.5 * weight* (predMatrix[i][j] - filledMatrix[i][j]) * (predMatrix[i][j] - filledMatrix[i][j]);
            }
        }
    }

    // regularization
    for (k = 0; k < dim; k++) {
        for (i = 0; i < numUser; i++) {
            loss += 0.5 * lmda * U[i][k] * U[i][k];
        }
        for (j = 0; j < numService; j++) {
            loss += 0.5 * lmda * S[j][k] * S[j][k];
        }
    }

    return loss;
}


void U_dot_S(double **filledMatrix, double **U, double **S, int numUser,
        int numService, int dim, double **predMatrix)
{
    int i, j;
    for (i = 0; i < numUser; i++) {
        for (j = 0; j < numService; j++) {
            if (filledMatrix[i][j] > 0) {
                predMatrix[i][j] = dotProduct(U[i], S[j], dim);
            }
        }
    }
}


double **vector2Matrix(double *vector, int row, int col)
{
    double **matrix = new double *[row];
    if (!matrix) {
        cout << "Memory allocation failed in vector2Matrix." << endl;
        return NULL;
    }

    int i;
    for (i = 0; i < row; i++) {
        matrix[i] = vector + i * col;
    }
    return matrix;
}


double dotProduct(double *vec1, double *vec2, int len)
{
    double product = 0;
    int i;
    for (i = 0; i < len; i++) {
        product += vec1[i] * vec2[i];
    }
    return product;
}


double **createMatrix(int row, int col)
{
    double **matrix = new double *[row];
    matrix[0] = new double[row * col];
    memset(matrix[0], 0, row * col * sizeof(double)); // Initialization
    int i;
    for (i = 1; i < row; i++) {
        matrix[i] = matrix[i - 1] + col;
    }
    return matrix;
}


void delete2DMatrix(double **ptr) {
    delete ptr[0];
    delete ptr;
}


void transpose(double **matrix, double **matrix_T, int row, int col)
{
    int i, j;
    for (i = 0; i < row; i++) {
        for (j = 0; j < col; j++) {
            matrix_T[j][i] = matrix[i][j];
        }
    }
}

Guess you like

Origin www.cnblogs.com/xinmomoyan/p/12102610.html