进销存系统智能推荐算法设计与实现
智能推荐概述
在进销存系统中,智能推荐可以帮助企业发现销售机会、优化库存结构、提升客户满意度。本文介绍商品推荐、关联销售和用户行为分析的实现方案。
推荐系统架构
推荐系统整体架构包含数据层、算法层、服务层和应用层:
| 层次 | 功能 | 技术选型 |
|---|---|---|
| 数据层 | 用户行为采集、商品数据存储 | MySQL、Redis |
| 算法层 | 协同过滤、关联规则、排序模型 | Python、TensorFlow |
| 服务层 | 推荐接口、实时推荐、AB测试 | Koa.js |
| 应用层 | Web端、小程序、APP展示 | Vue、React |
核心推荐算法
1. 协同过滤推荐
基于用户或商品的相似度进行推荐:
// 协同过滤推荐服务
class CollaborativeFiltering {
// 计算用户相似度(余弦相似度)
calculateUserSimilarity(userId1, userId2) {
const ratings1 = this.getUserRatings(userId1);
const ratings2 = this.getUserRatings(userId2);
// 找出两个用户共同评分过的商品
const commonItems = Object.keys(ratings1).filter(
item => item in ratings2
);
if (commonItems.length === 0) return 0;
// 构建向量
const vec1 = commonItems.map(item => ratings1[item]);
const vec2 = commonItems.map(item => ratings2[item]);
return this.cosineSimilarity(vec1, vec2);
}
// 基于用户的推荐
getUserBasedRecommendations(userId, topN = 10) {
// 找到相似用户
const allUsers = this.getAllUsers();
const similarities = allUsers
.filter(id => id !== userId)
.map(id => ({
userId: id,
similarity: this.calculateUserSimilarity(userId, id)
}))
.sort((a, b) => b.similarity - a.similarity)
.slice(0, 20); // 取Top20相似用户
// 获取目标用户未购买商品
const userPurchased = this.getUserPurchasedItems(userId);
const allItems = this.getAllItems();
const unpurchasedItems = allItems.filter(
item => !userPurchased.includes(item.id)
);
// 计算推荐分数
const scores = unpurchasedItems.map(item => {
let score = 0;
let weightSum = 0;
similarities.forEach(({ userId, similarity }) => {
if (similarity > 0) {
const rating = this.getRating(userId, item.id) || 0;
score += similarity * rating;
weightSum += similarity;
}
});
return {
item,
score: weightSum > 0 ? score / weightSum : 0
};
});
return scores
.sort((a, b) => b.score - a.score)
.slice(0, topN);
}
// 余弦相似度计算
cosineSimilarity(vec1, vec2) {
const dotProduct = vec1.reduce((sum, v, i) => sum + v * vec2[i], 0);
const magnitude1 = Math.sqrt(vec1.reduce((sum, v) => sum + v * v, 0));
const magnitude2 = Math.sqrt(vec2.reduce((sum, v) => sum + v * v, 0));
if (magnitude1 === 0 || magnitude2 === 0) return 0;
return dotProduct / (magnitude1 * magnitude2);
}
}
2. 关联规则挖掘
使用Apriori算法挖掘商品关联关系:
// 关联规则推荐
class AssociationRecommender {
// Apriori算法 - 找出频繁项集
apriori(transactions, minSupport = 0.01) {
// 统计单项支持度
const itemCounts = {};
transactions.forEach(t => {
t.items.forEach(item => {
itemCounts[item] = (itemCounts[item] || 0) + 1;
});
});
const totalTransactions = transactions.length;
const frequentItems = Object.entries(itemCounts)
.filter(([_, count]) => count / totalTransactions >= minSupport)
.map(([item]) => [item]);
// 迭代生成候选项集
let currentFrequent = frequentItems;
const allFrequent = [currentFrequent];
while (currentFrequent.length > 0) {
const candidates = this.generateCandidates(currentFrequent);
// 统计候选项支持度
const candidateCounts = {};
transactions.forEach(t => {
const itemSet = new Set(t.items);
candidates.forEach(candidate => {
if (candidate.every(item => itemSet.has(item))) {
const key = candidate.join(',');
candidateCounts[key] = (candidateCounts[key] || 0) + 1;
}
});
});
currentFrequent = Object.entries(candidateCounts)
.filter(([_, count]) => count / totalTransactions >= minSupport)
.map(([key]) => key.split(','));
if (currentFrequent.length > 0) {
allFrequent.push(currentFrequent);
}
}
return allFrequent.flat();
}
// 生成候选项集
generateCandidates(prevItemsets) {
const candidates = [];
for (let i = 0; i < prevItemsets.length; i++) {
for (let j = i + 1; j < prevItemsets.length; j++) {
const combined = [...new Set([...prevItemsets[i], ...prevItemsets[j]])];
if (combined.length === prevItemsets[0].length + 1) {
candidates.push(combined.sort());
}
}
}
return candidates;
}
// 计算关联规则置信度
calculateConfidence(rule, transactions) {
const { antecedent, consequent } = rule;
// 支持度 P(A∪B)
const abSupport = this.getSupport(antecedent.concat(consequent), transactions);
// 前件支持度 P(A)
const aSupport = this.getSupport(antecedent, transactions);
// 置信度 P(B|A) = P(A∪B) / P(A)
return aSupport > 0 ? abSupport / aSupport : 0;
}
// 获取某个项集的支持度
getSupport(itemset, transactions) {
let count = 0;
transactions.forEach(t => {
const itemSet = new Set(t.items);
if (itemset.every(item => itemSet.has(item))) {
count++;
}
});
return count / transactions.length;
}
// 生成推荐规则
generateRules(frequentItemsets, transactions, minConfidence = 0.5) {
const rules = [];
frequentItemsets.forEach(itemset => {
if (itemset.length < 2) return;
// 生成所有可能的规则
for (let i = 1; i < itemset.length; i++) {
const combinations = this.getCombinations(itemset, i);
combinations.forEach(antecedent => {
const consequent = itemset.filter(item => !antecedent.includes(item));
const confidence = this.calculateConfidence(
{ antecedent, consequent },
transactions
);
if (confidence >= minConfidence) {
rules.push({
antecedent,
consequent,
confidence,
support: this.getSupport(itemset, transactions)
});
}
});
}
});
return rules.sort((a, b) => b.confidence - a.confidence);
}
}
3. 基于销售数据的智能补货推荐
结合历史销售数据预测补货需求:
// 智能补货推荐
class ReplenishmentRecommender {
constructor() {
this.seasonalFactors = {}; // 季节性因子
}
// 计算加权移动平均预测
predictSales(productId, futureDate) {
const historicalData = this.getSalesHistory(productId, 90); // 90天历史
// 权重:近期数据权重更高
const weights = [0.5, 0.3, 0.2].reverse();
const recentData = historicalData.slice(-weights.length);
// 计算基础预测
const basePred = recentData.reduce(
(sum, sale, i) => sum + sale.quantity * weights[i],
0
);
// 考虑季节性因子
const month = new Date(futureDate).getMonth();
const seasonalFactor = this.getSeasonalFactor(productId, month);
// 考虑增长趋势
const trendFactor = this.calculateTrend(historicalData);
return Math.round(basePred * seasonalFactor * trendFactor);
}
// 计算推荐补货量
calculateReorderQuantity(productId) {
const currentStock = this.getCurrentStock(productId);
const safetyStock = this.getSafetyStock(productId); // 安全库存
const leadTime = this.getSupplierLeadTime(productId); // 供货周期
// 预测补货周期内的销量
let predictedDemand = 0;
for (let i = 1; i <= leadTime; i++) {
const futureDate = new Date();
futureDate.setDate(futureDate.getDate() + i);
predictedDemand += this.predictSales(productId, futureDate);
}
// 补货量 = 安全库存 + 预测需求 - 当前库存
const reorderQty = safetyStock + predictedDemand - currentStock;
return Math.max(0, Math.ceil(reorderQty));
}
// 获取季节性因子
getSeasonalFactor(productId, month) {
// 从历史数据计算月度销售占比
const monthlySales = this.getMonthlySales(productId);
const totalSales = monthlySales.reduce((sum, m) => sum + m.quantity, 0);
if (totalSales === 0) return 1;
const monthSales = monthlySales.find(m => m.month === month);
return monthSales ? monthSales.quantity / (totalSales / 12) : 1;
}
}
实时推荐服务
提供API接口供各端调用:
// 推荐API服务
router.get('/api/recommendations', async (ctx) => {
const userId = ctx.query.userId;
const type = ctx.query.type || 'personalized';
const limit = parseInt(ctx.query.limit) || 10;
let recommendations = [];
switch (type) {
case 'personalized':
// 个性化推荐
recommendations = await recommender.getPersonalizedRecommendations(
userId, limit
);
break;
case 'popular':
// 热销推荐
recommendations = await recommender.getPopularProducts(limit);
break;
case 'similar':
// 商品相似推荐
const productId = ctx.query.productId;
recommendations = await recommender.getSimilarProducts(
productId, limit
);
break;
case 'frequently_bought':
// 经常一起购买
const targetProductId = ctx.query.productId;
recommendations = await recommender.getFrequentlyBoughtTogether(
targetProductId
);
break;
case 'replenishment':
// 补货推荐(管理员)
if (!await checkAdminPermission(ctx)) {
ctx.status = 403;
return;
}
recommendations = await replenishmentRecommender.getReplenishmentList();
break;
}
ctx.body = {
success: true,
data: recommendations,
type,
generatedAt: new Date().toISOString()
};
});
效果评估与优化
推荐系统需要持续评估和优化:
| 指标 | 说明 | 目标 |
|---|---|---|
| 点击率(CTR) | 推荐商品被点击的比例 | >15% |
| 转化率 | 点击后购买的比例 | >8% |
| 客单价 | 使用推荐后的平均订单金额 | 提升10%+ |
| 覆盖率 | 被推荐到的商品比例 | >60% |
总结
进销存系统的智能推荐功能可以显著提升销售效率和客户体验。通过协同过滤、关联规则和智能补货等算法,为企业提供精准的商品推荐和库存优化建议。