进销存系统智能需求预测与供应链协同
引言
需求预测是进销存系统的核心功能之一,准确的需求预测可以优化库存水平、减少资金占用、提高供货及时率。本文将介绍如何利用机器学习算法构建智能需求预测系统,实现供应链的协同优化。
需求预测框架
智能需求预测的整体架构:
| 层次 | 组件 | 职责 |
|---|---|---|
| 数据层 | 销售数据、库存数据、外部数据 | 数据采集、清洗、存储 |
| 特征层 | 时间特征、统计特征、外部特征 | 特征工程、特征选择 |
| 模型层 | ARIMA、Prophet、LSTM、XGBoost | 预测模型训练与推理 |
| 应用层 | 采购建议、库存优化、预警提醒 | 预测结果应用 |
时间序列预测模型
基于历史销售数据的时间序列预测:
// 时间序列预测器
class TimeSeriesForecaster {
constructor(config) {
this.predictionHorizon = config.predictionHorizon || 30; // 预测天数
this.confidenceLevel = config.confidenceLevel || 0.95;
this.seasonality = config.seasonality || { weekly: 7, yearly: 365 };
}
// 预测主方法
async forecast(productId, historicalData) {
// 数据预处理
const cleanData = this.preprocess(historicalData);
// 多个模型预测
const predictions = await Promise.all([
this.arimaForecast(cleanData),
this.prophetForecast(cleanData),
this.exponentialSmoothing(cleanData)
]);
// 模型融合
const ensembleResult = this.ensemblePredictions(predictions);
// 计算置信区间
const confidenceInterval = this.calculateConfidenceInterval(
cleanData,
ensembleResult
);
return {
productId,
predictions: ensembleResult,
confidenceLower: confidenceInterval.lower,
confidenceUpper: confidenceInterval.upper,
accuracy: this.calculateAccuracy(cleanData, ensembleResult)
};
}
// ARIMA 模型预测
async arimaForecast(data) {
// 差分处理使序列平稳
const d = this.calculateDifferencingOrder(data);
const differenced = this.difference(data, d);
// ACF 和 PACF 分析确定参数
const { p, q } = this.identifyOrders(differenced);
// 拟合 ARIMA 模型
const model = this.fitARIMA(data, p, d, q);
// 多步预测
return this.forecastSteps(model, this.predictionHorizon);
}
// 指数平滑预测
exponentialSmoothing(data) {
const alpha = 0.3; // 平滑系数
const beta = 0.1; // 趋势平滑系数
const gamma = 0.2; // 季节性平滑系数
let level = data[0];
let trend = 0;
const seasonal = new Array(this.seasonality.weekly).fill(1);
const fitted = [];
const residuals = [];
for (let i = 0; i < data.length; i++) {
const season = seasonal[i % this.seasonality.weekly];
// 计算预测值
const yhat = (level + trend) * season;
fitted.push(yhat);
// 计算残差
residuals.push(data[i] - yhat);
// 更新参数
const newLevel = alpha * (data[i] / season) + (1 - alpha) * (level + trend);
const newTrend = beta * (newLevel - level) + (1 - beta) * trend;
const newSeason = gamma * (data[i] / newLevel) + (1 - gamma) * season;
level = newLevel;
trend = newTrend;
seasonal[i % this.seasonality.weekly] = newSeason;
}
// 未来预测
const forecasts = [];
for (let h = 1; h <= this.predictionHorizon; h++) {
const futureSeason = seasonal[h % this.seasonality.weekly];
forecasts.push((level + h * trend) * futureSeason);
}
return { forecasts, weight: 0.3 };
}
// Prophet 模型预测
async prophetForecast(data) {
// 将数据转换为 Prophet 格式
const df = this.toProphetFormat(data);
// 拟合模型
const model = {
trend: this.fitTrend(df),
seasonality: this.extractSeasonality(df),
holidays: this.extractHolidays(df)
};
// 生成未来日期
const futureDates = this.generateFutureDates(this.predictionHorizon);
// 预测
const forecasts = futureDates.map(date => {
let prediction = model.trend.predict(date);
// 叠加季节性
prediction += model.seasonality.weekly(date);
prediction += model.seasonality.yearly(date);
// 叠加节假日效应
prediction += model.holidays.effect(date);
return Math.max(0, prediction);
});
return { forecasts, weight: 0.4 };
}
// 模型融合
ensemblePredictions(predictions) {
const weights = predictions.map(p => p.weight);
const totalWeight = weights.reduce((a, b) => a + b, 0);
const normalizedWeights = weights.map(w => w / totalWeight);
const ensemble = [];
for (let i = 0; i < this.predictionHorizon; i++) {
let sum = 0;
for (let j = 0; j < predictions.length; j++) {
sum += predictions[j].forecasts[i] * normalizedWeights[j];
}
ensemble.push(sum);
}
return ensemble;
}
// 置信区间计算
calculateConfidenceInterval(data, predictions) {
// 计算历史预测误差
const errors = this.calculatePredictionErrors(data, predictions.slice(0, data.length));
const meanError = errors.reduce((a, b) => a + b, 0) / errors.length;
const stdError = Math.sqrt(
errors.reduce((sum, e) => sum + Math.pow(e - meanError, 2), 0) / errors.length
);
// z 值查表(95%置信度)
const zValue = 1.96;
const lower = predictions.map(p => Math.max(0, p - zValue * stdError));
const upper = predictions.map(p => p + zValue * stdError);
return { lower, upper };
}
}
特征工程
构建丰富的预测特征:
// 特征工程
class FeatureEngineering {
constructor() {
this.featureCache = new Map();
}
// 生成完整特征集
generateFeatures(productId, date, context) {
const features = {
// 时间特征
...this.extractTimeFeatures(date),
// 历史销售特征
...this.extractSalesFeatures(productId, date),
// 库存特征
...this.extractInventoryFeatures(productId, date),
// 外部特征
...this.extractExternalFeatures(date, context),
// 交互特征
...this.extractInteractionFeatures(productId, date)
};
return features;
}
// 时间特征提取
extractTimeFeatures(date) {
const d = new Date(date);
return {
year: d.getFullYear(),
month: d.getMonth() + 1,
day: d.getDate(),
dayOfWeek: d.getDay(),
dayOfYear: this.getDayOfYear(d),
weekOfYear: this.getWeekOfYear(d),
isWeekend: d.getDay() === 0 || d.getDay() === 6,
isMonthStart: d.getDate() === 1,
isMonthEnd: d.getDate() === this.getMonthEnd(d),
isQuarterStart: this.isQuarterStart(d),
isQuarterEnd: this.isQuarterEnd(d),
isYearStart: d.getMonth() === 0 && d.getDate() === 1,
isYearEnd: d.getMonth() === 11 && d.getDate() === 31,
season: this.getSeason(d),
// 节假日特征
isHoliday: this.isHoliday(d),
isPreHoliday: this.isPreHoliday(d),
isPostHoliday: this.isPostHoliday(d),
daysToHoliday: this.daysToHoliday(d),
holidayDuration: this.getHolidayDuration(d)
};
}
// 历史销售特征
extractSalesFeatures(productId, date) {
const history = this.getSalesHistory(productId, date);
return {
// 移动平均
sales_ma_7: this.calculateMA(history, 7),
sales_ma_14: this.calculateMA(history, 14),
sales_ma_30: this.calculateMA(history, 30),
// 指数移动平均
sales_ema_7: this.calculateEMA(history, 7),
sales_ema_14: this.calculateEMA(history, 14),
// 变化率
sales_change_7: this.calculateChangeRate(history, 7),
sales_change_14: this.calculateChangeRate(history, 14),
sales_change_30: this.calculateChangeRate(history, 30),
// 波动性
sales_std_7: this.calculateStd(history, 7),
sales_std_14: this.calculateStd(history, 14),
sales_std_30: this.calculateStd(history, 30),
// 同比环比
sales_yoy: this.calculateYoY(productId, date), // 同比
sales_mom: this.calculateMoM(productId, date), // 环比
// 累计销售
cumulative_sales_30: this.calculateCumulative(history, 30),
// 峰值特征
sales_max_30: this.calculateMax(history, 30),
sales_min_30: this.calculateMin(history, 30),
// 季节性指标
seasonal_index: this.calculateSeasonalIndex(productId, date)
};
}
// 库存特征
extractInventoryFeatures(productId, date) {
const inventory = this.getInventoryLevel(productId, date);
const safetyStock = this.getSafetyStock(productId);
return {
current_stock: inventory,
safety_stock: safetyStock,
stock_ratio: inventory / safetyStock,
is_low_stock: inventory < safetyStock,
stock_coverage_days: inventory / this.getAvgDailySales(productId),
reorder_point: this.calculateReorderPoint(productId),
is_need_reorder: inventory < this.calculateReorderPoint(productId)
};
}
// 外部特征
extractExternalFeatures(date, context = {}) {
return {
// 天气特征(如果有)
weather: context.weather || 'unknown',
temperature: context.temperature || 0,
// 促销活动
has_promotion: context.hasPromotion || false,
promotion_discount: context.promotionDiscount || 0,
promotion_type: context.promotionType || 'none',
// 竞争对手
competitor_price_change: context.competitorPriceChange || 0,
// 经济指标
consumer_confidence_index: context.cci || 50,
// 特殊事件
has_special_event: context.hasSpecialEvent || false,
event_type: context.eventType || 'none'
};
}
// 同比计算
calculateYoY(productId, date) {
const currentDate = new Date(date);
const lastYearDate = new Date(date);
lastYearDate.setFullYear(currentDate.getFullYear() - 1);
const currentSales = this.getSales(productId, date, 30);
const lastYearSales = this.getSales(productId, lastYearDate, 30);
if (lastYearSales === 0) return 0;
return (currentSales - lastYearSales) / lastYearSales;
}
// 环比计算
calculateMoM(productId, date) {
const currentDate = new Date(date);
const lastMonthDate = new Date(date);
lastMonthDate.setMonth(currentDate.getMonth() - 1);
const currentSales = this.getSales(productId, date, 30);
const lastMonthSales = this.getSales(productId, lastMonthDate, 30);
if (lastMonthSales === 0) return 0;
return (currentSales - lastMonthSales) / lastMonthSales;
}
// 季节性指数
calculateSeasonalIndex(productId, date) {
const d = new Date(date);
const month = d.getMonth();
// 获取该商品历史的月度销售数据
const monthlySales = this.getMonthlySalesPattern(productId);
// 计算季节性指数
const monthlyAvg = monthlySales.reduce((a, b) => a + b, 0) / 12;
return monthlySales[month] / monthlyAvg;
}
}
库存优化策略
基于预测的库存优化:
// 库存优化器
class InventoryOptimizer {
constructor(config) {
this.serviceLevel = config.serviceLevel || 0.95;
this.holdingCost = config.holdingCost || 0.2; // 年持有成本率
this.orderCost = config.orderCost || 100; // 每次订货成本
this.leadTime = config.leadTime || 7; // 采购提前期(天)
}
// 计算安全库存
calculateSafetyStock(productId, forecast, variability) {
// 使用改进的安全库存公式
const z = this.getZScore(this.serviceLevel);
const sigma = this.calculateDemandVariability(forecast, variability);
const leadTime = this.getLeadTime(productId);
// 安全库存 = z * sigma * sqrt(Lead Time)
return Math.ceil(z * sigma * Math.sqrt(leadTime));
}
// 计算需求变异性
calculateDemandVariability(forecast, variability) {
// 考虑预测误差
const forecastError = variability.forecastError || 0.2;
const demandStd = forecast * forecastError;
// 考虑需求波动
const demandVariation = variability.demandVariation || 0.3;
return Math.max(demandStd, forecast * demandVariation);
}
// 计算再订货点
calculateReorderPoint(productId, forecast, safetyStock) {
const avgLeadTime = this.getAvgLeadTime(productId);
const avgDailySales = forecast;
// 再订货点 = 平均需求 * 平均交货期 + 安全库存
return Math.ceil(avgDailySales * avgLeadTime + safetyStock);
}
// 计算最优订货量(EOQ)
calculateEOQ(annualDemand, unitCost) {
// 经济订货量公式
const eoq = Math.sqrt(
(2 * annualDemand * this.orderCost) /
(unitCost * this.holdingCost)
);
return Math.ceil(eoq);
}
// 生成补货建议
generateReplenishmentRecommendation(productId, forecast, currentStock) {
const product = this.getProductInfo(productId);
const leadTime = this.getLeadTime(productId);
// 计算各期间预测需求
const forecastedDemand = forecast.predictions.slice(0, leadTime + 30);
const totalForecast = forecastedDemand.reduce((a, b) => a + b, 0);
// 计算安全库存
const variability = this.getDemandVariability(productId);
const safetyStock = this.calculateSafetyStock(productId, forecast.predictions[0], variability);
// 计算再订货点
const reorderPoint = this.calculateReorderPoint(
productId,
forecast.predictions[0],
safetyStock
);
// 检查是否需要补货
const needsReorder = currentStock <= reorderPoint;
const stockoutRisk = this.calculateStockoutRisk(currentStock, forecast, leadTime);
// 计算建议订货量
const targetStock = Math.ceil(
forecast.predictions[0] * (leadTime + 30) + safetyStock
);
const recommendedOrderQty = Math.max(0, targetStock - currentStock);
// 检查最小起订量
const finalOrderQty = Math.max(
recommendedOrderQty,
product.minOrderQty || 0
);
return {
productId,
currentStock,
safetyStock,
reorderPoint,
needsReorder,
stockoutRisk,
recommendedOrderQty: finalOrderQty,
expectedStockAfterOrder: currentStock + finalOrderQty,
stockoutDate: this.estimateStockoutDate(currentStock, forecast),
optimalReorderDate: this.calculateOptimalReorderDate(
currentStock,
forecast,
leadTime,
reorderPoint
)
};
}
// 计算缺货风险
calculateStockoutRisk(currentStock, forecast, leadTime) {
const leadTimeDemand = forecast.predictions.slice(0, leadTime).reduce((a, b) => a + b, 0);
const variance = this.calculateVariance(forecast.predictions.slice(0, leadTime));
// 使用正态分布近似
const z = (currentStock - leadTimeDemand) / Math.sqrt(variance);
const probability = 1 - this.normalCDF(z);
return probability;
}
// 计算最佳补货日期
calculateOptimalReorderDate(currentStock, forecast, leadTime, reorderPoint) {
const dailySales = forecast.predictions[0];
// 计算多少天后会达到再订货点
const daysToReorder = currentStock > reorderPoint
? (currentStock - reorderPoint) / dailySales
: 0;
// 考虑交货期,提前一些天数下单
const optimalDate = new Date();
optimalDate.setDate(optimalDate.getDate() + Math.max(0, daysToReorder - leadTime));
return optimalDate.toISOString().split('T')[0];
}
}
供应链协同
实现供应链上下游协同:
// 供应链协同平台
class SupplyChainCollaboration {
constructor() {
this.vendors = new Map();
this.distributors = new Map();
}
// 需求共享
async shareDemandForecast(vendorId, forecasts) {
const vendor = this.vendors.get(vendorId);
// 发送预测需求给供应商
await this.sendToVendor(vendorId, {
type: 'demand_forecast',
forecasts: forecasts.map(f => ({
productId: f.productId,
date: f.date,
quantity: f.quantity,
confidence: f.confidence
})),
requestDate: new Date().toISOString()
});
// 记录共享历史
await this.logDemandShare(vendorId, forecasts);
}
// 供应商响应
async vendorResponse(vendorId, productId, response) {
const {
confirmedDate,
confirmedQuantity,
alternativeProducts,
priceAdjustment,
capacityConstraint
} = response;
// 更新预测的确定性
await this.updateForecastCertainty(productId, {
vendorId,
confirmedDate,
confirmedQuantity,
reliability: this.calculateReliability(vendorId)
});
// 检查是否有产能约束
if (capacityConstraint) {
await this.handleCapacityConstraint(vendorId, productId, capacityConstraint);
}
return {
accepted: confirmedQuantity > 0,
leadTime: this.getLeadTimeDays(new Date(), confirmedDate),
unitPrice: response.price
};
}
// 库存可视化共享
async shareInventoryLevel(partnerId, inventoryData) {
return await this.syncToPartner(partnerId, {
type: 'inventory_update',
data: inventoryData.map(item => ({
productId: item.productId,
quantity: item.quantity,
warehouse: item.warehouse,
reserved: item.reserved,
available: item.available
})),
timestamp: new Date().toISOString()
});
}
// 自动补货协议
async setupAutoReplenishment(customerId, vendorId, agreement) {
const {
productId,
minStock,
maxStock,
reorderPoint,
quantity,
frequency
} = agreement;
// 创建自动补货规则
const rule = {
id: this.generateRuleId(),
customerId,
vendorId,
productId,
condition: `stock <= ${reorderPoint}`,
action: {
type: 'create_purchase_order',
quantity: quantity,
autoApprove: true
},
schedule: frequency,
status: 'active'
};
await this.saveAutoReplenishmentRule(rule);
return rule;
}
// 协同计划排产
async collaborativePlanning(orders, constraints) {
// 收集所有参与者的能力和约束
const participants = await this.getAllParticipants();
// 运行协同计划算法
const plan = await this.optimizeProductionPlan(
orders,
participants,
constraints
);
// 分发计划给各参与者
for (const participant of participants) {
const participantPlan = this.extractParticipantPlan(plan, participant.id);
await this.sendPlanToParticipant(participant.id, participantPlan);
}
return plan;
}
// 订单状态同步
async syncOrderStatus(orderId) {
const order = await this.getOrder(orderId);
const statusHistory = [];
// 追踪订单在各环节的状态
for (const step of order.steps) {
const status = await this.getStepStatus(orderId, step);
statusHistory.push({
step: step.name,
status: status.state,
timestamp: status.timestamp,
location: status.location
});
}
return statusHistory;
}
}
最佳实践建议
- 数据质量:确保历史销售数据的完整性和准确性
- 模型选择:根据数据特点选择合适的预测模型
- 持续优化:定期评估预测准确率,持续调整模型参数
- 安全库存:根据服务水平要求设置合理的安全库存
- 协同沟通:与供应商建立需求共享机制,提高供应链响应速度
总结
智能需求预测与供应链协同是提升企业运营效率的关键:
- 预测算法:多种算法融合,提高预测准确度
- 特征工程:丰富的特征提升模型效果
- 库存优化:EOQ和再订货点优化库存成本
- 供应链协同:上下游信息共享,提升整体效率
通过智能预测与协同,企业可以实现供需匹配,降低运营成本。