面对海量的商品信息如何实现针对不同用户维度开展个性化商品推荐,实现用户线上选购商品,下订单,支付,物流配送等?本次毕设程序基于前后端分离开发模式,搭建系统网络商品推荐系统前台与系统后台商品管理系统,通过可以配置的方式一体化管理商品信息,推送商品内容,生成丰富的可视化统计分析。
一、程序设计
本次商品推荐及管理系统主要内容涉及:
主要功能模块:商品推荐网站前台,商品管理系统后台
主要包含技术:springboot,mybatisplus,mysql,javascript,vue.js,html,css
主要包含算法:基于用户协同过滤推荐算法
系统采用前后端分离的开发模式完成,商品推荐网站前台要采用Vue.js,javascript,html,CSS等技术实现。系统前后端数据交互,采用Ajax异步调用传输JSON实现。
商品推荐网站前台主要包括以下功能清单:
用户登录注册
商品轮播图
商品分类展示
商品推荐展示
用户购物车
订单管理
订单配送管理
个人中心
修改密码
商品管理系统后台主要包括以下功能清单:
管理员登录
商品管理
轮播图配置
热销商品配置
新品上线配置
为您推荐配置
商品分类管理
会员管理
订单管理
二、效果实现
网站登录
系统主页
商品详情
购物车
我的订单
后台商品管理
轮播图管理
订单管理
热销商品管理
其他效果省略
三、商品推荐设计
本次毕设系统在商品推荐算法设计中,主要采用基于用户协同过滤算法 商品内容关键词统计分析计算两种方式,其中基于用户协同过滤推荐算法主要利用用户历史购买商品的情况,开展相似用户计算,商品关键词统计则是按照商品特征开展计算,两种计算方式结合优化商品推荐精准度。系统推荐流程,如下图所示:
基于用户协同过滤推荐算法实现
java实现协同过滤推荐算法代码
代码语言:java复制 class UserBaseCF{
public static final int USERSIZE=943;
public static final int ITEMSIZE=1682;
public static final int UN=10;//某一user的最近邻居数
//public static final int IN=10;//某一item的最近邻居数
public int [] num=new int[USERSIZE 1];//每个用户为几部评了分
public double[] average=new double[USERSIZE 1];//每个user的平均打分
public double[][] rate=new double[USERSIZE 1][ITEMSIZE 1];//评分矩阵
public double[][] DealedOfRate=new double[USERSIZE 1][ITEMSIZE 1];//针对稀疏问题处理后的评分矩阵
Neighbor[][] NofUser =new Neighbor[USERSIZE 1][UN 1];//每个用户的最近的UN个邻居
List<Double> x=new LinkedList<Double>();//LinkedList按照对象加入的顺序存储
List<Double> y=new LinkedList<Double>();
public static void main(String args[]) throws Exception{
UserBaseCF cf=new UserBaseCF();
if(cf.readFile("bin/ml-data_0/u1.base")){
System.out.println("请等待,正在分析");
cf.getAvr();//得到average[]
cf.dealRate();//得到DealedOfRate
cf.getNofUser();//得到NofUser
for(int i=1;i<=UN;i ){
System.out.println(cf.NofUser[1][i].getID() ":" cf.NofUser[1][i].getValue());
}
//读文件
File inputFile=new File("bin/ml-data_0/u1.test");
BufferedReader reader=null;
if(!inputFile.exists()||inputFile.isDirectory())
throw new FileNotFoundException();
reader=new BufferedReader(new FileReader(inputFile));
//写文件
File outputFile=new File("bin/testResult.txt");
FileWriter writer=null;
if(!outputFile.exists())
if(!outputFile.createNewFile())
System.out.println("输出文件创建失败");
writer=new FileWriter(outputFile);
String title ="UserID" "t" "ItemID" "t" "OriginalRate" "t" "PredictRate" "rn";
writer.write(title);
writer.flush();
String[] part=new String[3];
String tmpToRead="";
String tmpToWrite="";
while((tmpToRead=reader.readLine())!=null){
part=tmpToRead.split("t");
int userID=Integer.parseInt(part[0]);
int itemID=Integer.parseInt(part[1]);
double originalRate=Double.parseDouble(part[2]);
double predictRate=cf.predict(userID, itemID);
cf.x.add(originalRate);
cf.y.add(predictRate);
tmpToWrite=userID "t" itemID "t" originalRate "t" predictRate "rn";
writer.write(tmpToWrite);
writer.flush();
}
System.out.println("分析完成,请打开工程目录下bin文件夹中的testResult.txt");
System.out.println("利用RMSE分析结果为" cf.analyse(cf.x, cf.y));
}
else
System.out.println("失败");
}
//Chapter1:准备工作
//1-1:读取文件内容,得到评分矩阵 1:读取成功 -1:读取失败
public boolean readFile(String filePath){
File inputFile=new File(filePath);
BufferedReader reader=null;
try {
reader=new BufferedReader(new FileReader(inputFile));
} catch (FileNotFoundException e) {
System.out.println("文件不存在" e.getMessage());
return false;
}
String sentence="";
String[] part=new String[3];
try {
while((sentence=reader.readLine())!=null){
part=sentence.split("t");
int userID=Integer.parseInt(part[0]);
int itemID=Integer.parseInt(part[1]);
double Rate=Double.parseDouble(part[2]);
//构造矩阵
rate[userID][itemID]=Rate;
}
} catch (NumberFormatException|IOException e) {
System.out.println("读文件发生错误" e.getMessage());
return false;
}
return true;
}
//1-2计算每个用户的平均分
public void getLen(){//计算每个用户为几部电影打分
for(int i=1;i<=USERSIZE;i ){
int n=0;
for(int j=1;j<=ITEMSIZE;j ){
if(rate[i][j]!=0)
n ;
}
num[i]=n;
}
}
public void getAvr(){
getLen();
int i,j;
for(i=1;i<=USERSIZE;i ){
double sum=0.0;
for(j=1;j<rate[i].length;j ){//每个length都是ITEMSIZE=1682
sum =rate[i][j];
}
average[i]=sum/num[i];
}
}
//1-3处理评分矩阵的稀疏问题(重要事项!!!)
//重点处理该user对没有被评分的item,会打几分
//暂时用1-2中计算出的平均分
public void dealRate(){
int i,j;
for(i=1;i<=USERSIZE;i ){
for(j=1;j<=ITEMSIZE;j ){
if(rate[i][j]==0)
DealedOfRate[i][j]=average[i];
else
DealedOfRate[i][j]=rate[i][j];
}
}
}
//Chapter2:聚类,找和某一用户有相同喜好的一类用户
//2-1::Pearson计算向量的相似度
public double Sum(double[] arr){
double total=(double)0.0;
for(double ele:arr)
total =ele;
return total;
}
public double Mutipl(double[] arr1,double[] arr2,int len){
double total=(double)0.0;
for(int i=0;i<len;i )
total =arr1[i]*arr2[i];
return total;
}
public double Pearson(double[] x,double[] y){
int lenx=x.length;
int leny=y.length;
int len=lenx;//小容错
if(lenx<leny) len=lenx;
else len=leny;
double sumX=Sum(x);
double sumY=Sum(y);
double sumXX=Mutipl(x,x,len);
double sumYY=Mutipl(y,y,len);
double sumXY=Mutipl(x,y,len);
double upside=sumXY-sumX*sumY/len;
//double downside=(double) Math.sqrt((sumXX-(Math.pow(sumX, 2))/len)*(sumYY-(Math.pow(sumY, 2))/len));
double downside=(double) Math.sqrt((sumXX-Math.pow(sumX, 2)/len)*(sumYY-Math.pow(sumY, 2)/len));
//System.out.println(len " " sumX " " sumY " " sumXX " " sumYY " " sumXY);
return upside/downside;
}
}
商品关键词统计分析计算
针对商品信息简历关键词库,采用TF-IDF对商品关键词进行加权分析处理,按照用户检索关键词匹配最佳商品推荐。
java实现关键词加权计算代码
代码语言:java复制//查询所有商品关键词库
List<String> skeys = keywordsList.stream().map(item -> item.getSkeys()).collect(Collectors.toList());
List skeyList = Lists.newArrayList();
if (CollectionUtils.isNotEmpty(skeys)) {
Map<String, Integer> sMap = new HashMap<>();
for (String item : skeys) {
List<String> strings = Arrays.asList(item.split(","));
if (CollectionUtils.isNotEmpty(strings)) {
strings.forEach(sItem -> {
if (StringUtils.isNotBlank(sItem)) {
if (sMap.containsKey(sItem)) {
sMap.put(sItem, sMap.get(sItem) 1);
} else {
sMap.put(sItem, 1);
}
}
});
}
}
for (Map.Entry<String, Integer> entry : sMap.entrySet()) {
skeyList.add(new HashMap() {{
put("name", entry.getKey());
put("value", entry.getValue());
}});
}
}