#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define U 21628//用户数,数组第一行不使用
#define M 41370//电影数+1,数组第一列不使用
#define F 11//语义维数+1
#define lambda 0.14//正规化参数1,过拟合参数
#define T 409158//训练集个数
#define P 174812//测试集个数
//定义全局变量
float train[T][3];
float test[P][3];
float w[U];
float bu[U];
float bi[M];
float user[U][F];//用户矩阵
float movie[M][F];//项目矩阵
float mean;//整体平均分
float alpha=0.01;
void Init_train()//训练集
{
int u,m;
float r;
FILE *fp;
if((fp=fopen("train_1M.txt", "r"))==NULL)
{
printf("没有train_1M.txt这个文件,无法导入数据\n");
exit(1);
}
printf("succeed\n");
int i=0;
while(!feof(fp))
{
i++;
fscanf(fp,"%d,%d,%f",&u,&m,&r);
train[i][0]=u;
train[i][1]=m;
train[i][2]=r;
}
}
void Init_test()//测试集
{
int u,m;
float r;
FILE *fp1;
if((fp1=fopen("test_1M.txt", "r"))==NULL)
{
printf("没有test_1M.txt这个文件,无法导入数据\n");
exit(1);
}
printf("succeed\n");
int i=0;
while(!feof(fp1))
{
i++;
fscanf(fp1,"%d,%d,%f",&u,&m,&r);
test[i][0]=u;
test[i][1]=m;
test[i][2]=r;
}
}
void average()
{
float sum=0;
for(int i=1;i<T;i++)//T是训练集个数
{
sum+=train[i][2];
}
mean=sum/(T-1);
printf("the mean:%f\n",mean);
}
void Init_UM()//初始化U,M语义矩阵
{
int i=1,j=0,f;
float t;
for(i=1;i<U;i++)
for(j=1;j<F;j++) //F为语义维数
{
t=(rand()%6);
user[i][j]=0.01*t;
}
for(i=1;i<M;i++)
for(j=1;j<F;j++)
{
t=(rand()%6);
movie[i][j]=0.01*t;
}
for(i=1;i<U;i++)
bu[i]=0;
for(i=1;i<M;i++)
bi[i]=0;
}
float pre_out(int u,int m)
{
float p=0;
for(int k=1;k<F;k++)
p+=user[u][k]*movie[m][k]; //预测评分
if(p>5)
p=5;
if(p<1)
p=1;
return p;
}
float gradient_descent(int step)//随机梯度下降法求U、M
{
int i,j,k,u,m;
for(i=1;i<T;i++)
{
u=(int)train[i][0];
m=(int)train[i][1];
for(k=1;k<F;k++)
{
user[u][k]+=alpha*((train[i][2]-pre_out(u,m))*movie[m][k]-lambda*user[u][k]);
movie[m][k]+=alpha*((train[i][2]-pre_out(u,m))*user[u][k]-lambda*movie[m][k]);
}
}
alpha=0.99*alpha;
float sum=0,sum2=0;
for(i=1;i<T;i++)
{
u=(int)train[i][0];
m=(int)train[i][1];
sum+=pow(pre_out(u,m)-train[i][2],2);
}
float RMSE=sqrt(sum/(T-1));
printf("step%d trainRMSE:%f ",step,RMSE);
sum=0;
for(i=1;i<P;i++) //P为测试集个数
{
u=(int)test[i][0];
m=(int)test[i][1];
float p=pre_out(u,m);
sum+=pow(p-test[i][2],2);
sum2+=fabs(p-test[i][2]);
}
float tRMSE=sqrt(sum/(P-1));
float tMAE=sum2/(P-1);
printf("testRMSE:%f testMAE:%f\n",tRMSE,tMAE);
return RMSE;
}
int main()
{
printf("alpha=%f lambda=%f\n",alpha,lambda);
Init_train();
Init_test();
average();
Init_UM();
float RMSE=10000,t;
for(int i=0;i<100;i++) //迭代100次
{
t=RMSE;
RMSE=gradient_descent(i);
if(RMSE>t)
break;
}
return 0;
}