701 lines
23 KiB
Markdown
701 lines
23 KiB
Markdown
![]() |
# 🔮 药店销售预测结果分析增强方案
|
|||
|
|
|||
|
## 一、预测结果解释系统设计 📊
|
|||
|
|
|||
|
### 1. 预测解释功能概述
|
|||
|
在现有的预测系统基础上,增加预测结果解释功能,不仅返回预测值,还提供对预测结果的分析解释,帮助用户理解"为什么会得到这样的预测结果"和"哪些因素影响了这个预测"。
|
|||
|
|
|||
|
### 2. 核心功能模块
|
|||
|
|
|||
|
#### A. 特征重要性分析
|
|||
|
```python
|
|||
|
def analyze_feature_importance(model, X_test, feature_names):
|
|||
|
"""
|
|||
|
分析各个特征对预测结果的重要性
|
|||
|
|
|||
|
Args:
|
|||
|
model: 训练好的模型
|
|||
|
X_test: 测试数据特征
|
|||
|
feature_names: 特征名称列表
|
|||
|
|
|||
|
Returns:
|
|||
|
feature_importance_dict: 特征重要性字典
|
|||
|
"""
|
|||
|
# 根据不同模型类型实现特征重要性计算
|
|||
|
if hasattr(model, 'feature_importances_'): # 如GBDT等树模型
|
|||
|
importances = model.feature_importances_
|
|||
|
else: # 对于深度学习模型,使用排列重要性或SHAP值
|
|||
|
importances = calculate_permutation_importance(model, X_test)
|
|||
|
|
|||
|
# 将特征名称与重要性值匹配
|
|||
|
feature_importance_dict = dict(zip(feature_names, importances))
|
|||
|
return feature_importance_dict
|
|||
|
```
|
|||
|
|
|||
|
#### B. 预测因素分解
|
|||
|
```python
|
|||
|
def decompose_prediction_factors(prediction, feature_values, feature_importance):
|
|||
|
"""
|
|||
|
将预测结果分解为各个因素的贡献
|
|||
|
|
|||
|
Args:
|
|||
|
prediction: 预测结果
|
|||
|
feature_values: 输入特征值
|
|||
|
feature_importance: 特征重要性
|
|||
|
|
|||
|
Returns:
|
|||
|
factor_contributions: 各因素对预测的贡献
|
|||
|
"""
|
|||
|
# 计算每个特征的贡献
|
|||
|
factor_contributions = {}
|
|||
|
for feature, value in feature_values.items():
|
|||
|
if feature in feature_importance:
|
|||
|
contribution = value * feature_importance[feature]
|
|||
|
factor_contributions[feature] = {
|
|||
|
'value': value,
|
|||
|
'importance': feature_importance[feature],
|
|||
|
'contribution': contribution
|
|||
|
}
|
|||
|
|
|||
|
# 按贡献大小排序
|
|||
|
sorted_factors = sorted(factor_contributions.items(),
|
|||
|
key=lambda x: abs(x[1]['contribution']),
|
|||
|
reverse=True)
|
|||
|
|
|||
|
return sorted_factors
|
|||
|
```
|
|||
|
|
|||
|
#### C. 历史模式匹配
|
|||
|
```python
|
|||
|
def find_similar_historical_patterns(current_prediction, historical_data, window_size=7):
|
|||
|
"""
|
|||
|
查找历史数据中与当前预测模式相似的时间段
|
|||
|
|
|||
|
Args:
|
|||
|
current_prediction: 当前预测结果序列
|
|||
|
historical_data: 历史数据
|
|||
|
window_size: 比较窗口大小
|
|||
|
|
|||
|
Returns:
|
|||
|
similar_patterns: 相似的历史模式列表
|
|||
|
"""
|
|||
|
similar_patterns = []
|
|||
|
|
|||
|
# 计算当前预测的特征(如趋势、周期性等)
|
|||
|
current_features = extract_pattern_features(current_prediction)
|
|||
|
|
|||
|
# 在历史数据中滑动窗口寻找相似模式
|
|||
|
for i in range(len(historical_data) - window_size):
|
|||
|
window = historical_data[i:i+window_size]
|
|||
|
window_features = extract_pattern_features(window)
|
|||
|
|
|||
|
# 计算相似度
|
|||
|
similarity = calculate_similarity(current_features, window_features)
|
|||
|
|
|||
|
if similarity > SIMILARITY_THRESHOLD:
|
|||
|
similar_patterns.append({
|
|||
|
'period': (i, i+window_size),
|
|||
|
'data': window,
|
|||
|
'similarity': similarity
|
|||
|
})
|
|||
|
|
|||
|
# 按相似度排序
|
|||
|
similar_patterns.sort(key=lambda x: x['similarity'], reverse=True)
|
|||
|
|
|||
|
return similar_patterns[:5] # 返回前5个最相似的模式
|
|||
|
```
|
|||
|
|
|||
|
#### D. 异常值检测与解释
|
|||
|
```python
|
|||
|
def detect_and_explain_anomalies(predictions, historical_stats):
|
|||
|
"""
|
|||
|
检测预测结果中的异常值并提供解释
|
|||
|
|
|||
|
Args:
|
|||
|
predictions: 预测结果序列
|
|||
|
historical_stats: 历史数据统计信息
|
|||
|
|
|||
|
Returns:
|
|||
|
anomalies: 异常值及其解释
|
|||
|
"""
|
|||
|
anomalies = []
|
|||
|
|
|||
|
# 计算预测值的统计特性
|
|||
|
mean = historical_stats['mean']
|
|||
|
std = historical_stats['std']
|
|||
|
|
|||
|
# 检测异常值(例如超过2个标准差)
|
|||
|
for i, value in enumerate(predictions):
|
|||
|
z_score = (value - mean) / std
|
|||
|
|
|||
|
if abs(z_score) > 2:
|
|||
|
# 异常值检测
|
|||
|
anomaly = {
|
|||
|
'day': i,
|
|||
|
'value': value,
|
|||
|
'z_score': z_score,
|
|||
|
'severity': 'high' if abs(z_score) > 3 else 'medium',
|
|||
|
'explanation': generate_anomaly_explanation(value, z_score, i)
|
|||
|
}
|
|||
|
anomalies.append(anomaly)
|
|||
|
|
|||
|
return anomalies
|
|||
|
```
|
|||
|
|
|||
|
## 二、预测结果解释API设计 🔌
|
|||
|
|
|||
|
### 1. API接口扩展
|
|||
|
```python
|
|||
|
@app.route('/api/prediction/explain', methods=['POST'])
|
|||
|
def explain_prediction():
|
|||
|
"""
|
|||
|
提供预测结果的详细解释
|
|||
|
---
|
|||
|
tags:
|
|||
|
- 预测分析
|
|||
|
parameters:
|
|||
|
- name: body
|
|||
|
in: body
|
|||
|
required: true
|
|||
|
schema:
|
|||
|
type: object
|
|||
|
properties:
|
|||
|
product_id:
|
|||
|
type: string
|
|||
|
example: P001
|
|||
|
model_type:
|
|||
|
type: string
|
|||
|
enum: [mlstm, transformer, kan, optimized_kan]
|
|||
|
future_days:
|
|||
|
type: integer
|
|||
|
default: 7
|
|||
|
include_factors:
|
|||
|
type: boolean
|
|||
|
default: true
|
|||
|
include_similar_patterns:
|
|||
|
type: boolean
|
|||
|
default: true
|
|||
|
include_anomaly_detection:
|
|||
|
type: boolean
|
|||
|
default: true
|
|||
|
responses:
|
|||
|
200:
|
|||
|
description: 预测结果及其解释
|
|||
|
"""
|
|||
|
data = request.json
|
|||
|
product_id = data.get('product_id')
|
|||
|
model_type = data.get('model_type')
|
|||
|
future_days = data.get('future_days', 7)
|
|||
|
|
|||
|
# 获取预测结果
|
|||
|
predictions, features = load_model_and_predict_with_features(
|
|||
|
product_id, model_type, future_days
|
|||
|
)
|
|||
|
|
|||
|
# 准备响应数据
|
|||
|
response = {
|
|||
|
'status': 'success',
|
|||
|
'predictions': predictions.tolist(),
|
|||
|
'explanation': {}
|
|||
|
}
|
|||
|
|
|||
|
# 根据请求参数添加不同类型的解释
|
|||
|
if data.get('include_factors', True):
|
|||
|
# 添加特征重要性分析
|
|||
|
model = load_model(product_id, model_type)
|
|||
|
feature_importance = analyze_feature_importance(model, features, FEATURE_NAMES)
|
|||
|
factor_contributions = decompose_prediction_factors(
|
|||
|
predictions, features, feature_importance
|
|||
|
)
|
|||
|
response['explanation']['factors'] = factor_contributions
|
|||
|
|
|||
|
if data.get('include_similar_patterns', True):
|
|||
|
# 添加历史模式匹配
|
|||
|
historical_data = load_historical_data(product_id)
|
|||
|
similar_patterns = find_similar_historical_patterns(
|
|||
|
predictions, historical_data
|
|||
|
)
|
|||
|
response['explanation']['similar_patterns'] = similar_patterns
|
|||
|
|
|||
|
if data.get('include_anomaly_detection', True):
|
|||
|
# 添加异常值检测
|
|||
|
historical_stats = calculate_historical_stats(product_id)
|
|||
|
anomalies = detect_and_explain_anomalies(predictions, historical_stats)
|
|||
|
response['explanation']['anomalies'] = anomalies
|
|||
|
|
|||
|
# 生成总体解释文本
|
|||
|
response['explanation']['summary'] = generate_explanation_summary(
|
|||
|
predictions, response['explanation']
|
|||
|
)
|
|||
|
|
|||
|
return jsonify(response)
|
|||
|
```
|
|||
|
|
|||
|
### 2. 前端展示组件
|
|||
|
|
|||
|
#### A. 预测结果解释面板
|
|||
|
```javascript
|
|||
|
// Vue组件示例
|
|||
|
<template>
|
|||
|
<div class="prediction-explanation">
|
|||
|
<el-card class="explanation-card">
|
|||
|
<div slot="header">
|
|||
|
<span>预测结果解释</span>
|
|||
|
</div>
|
|||
|
|
|||
|
<!-- 总体解释摘要 -->
|
|||
|
<div class="explanation-summary">
|
|||
|
<h4>预测分析摘要</h4>
|
|||
|
<p>{{ explanation.summary }}</p>
|
|||
|
</div>
|
|||
|
|
|||
|
<!-- 关键影响因素 -->
|
|||
|
<div v-if="explanation.factors" class="key-factors">
|
|||
|
<h4>关键影响因素</h4>
|
|||
|
<el-table :data="explanation.factors.slice(0, 5)" style="width: 100%">
|
|||
|
<el-table-column prop="factor" label="因素"></el-table-column>
|
|||
|
<el-table-column prop="contribution" label="贡献度">
|
|||
|
<template slot-scope="scope">
|
|||
|
<el-progress
|
|||
|
:percentage="Math.abs(scope.row.contribution * 100)"
|
|||
|
:color="scope.row.contribution > 0 ? '#67C23A' : '#F56C6C'"
|
|||
|
></el-progress>
|
|||
|
</template>
|
|||
|
</el-table-column>
|
|||
|
<el-table-column prop="impact" label="影响">
|
|||
|
<template slot-scope="scope">
|
|||
|
<span :class="scope.row.contribution > 0 ? 'positive' : 'negative'">
|
|||
|
{{ scope.row.contribution > 0 ? '增加' : '减少' }}
|
|||
|
</span>
|
|||
|
</template>
|
|||
|
</el-table-column>
|
|||
|
</el-table>
|
|||
|
</div>
|
|||
|
|
|||
|
<!-- 异常值提示 -->
|
|||
|
<div v-if="explanation.anomalies && explanation.anomalies.length > 0" class="anomalies">
|
|||
|
<h4>异常值提示</h4>
|
|||
|
<el-alert
|
|||
|
v-for="(anomaly, index) in explanation.anomalies"
|
|||
|
:key="index"
|
|||
|
:title="`第${anomaly.day + 1}天: ${anomaly.value} (${anomaly.severity}级异常)`"
|
|||
|
:type="anomaly.severity === 'high' ? 'error' : 'warning'"
|
|||
|
:description="anomaly.explanation"
|
|||
|
show-icon
|
|||
|
></el-alert>
|
|||
|
</div>
|
|||
|
|
|||
|
<!-- 相似历史模式 -->
|
|||
|
<div v-if="explanation.similar_patterns && explanation.similar_patterns.length > 0" class="similar-patterns">
|
|||
|
<h4>相似历史模式</h4>
|
|||
|
<el-collapse>
|
|||
|
<el-collapse-item
|
|||
|
v-for="(pattern, index) in explanation.similar_patterns"
|
|||
|
:key="index"
|
|||
|
:title="`相似模式 #${index + 1} (相似度: ${(pattern.similarity * 100).toFixed(1)}%)`"
|
|||
|
>
|
|||
|
<div class="pattern-chart">
|
|||
|
<line-chart :chart-data="prepareChartData(pattern.data)"></line-chart>
|
|||
|
</div>
|
|||
|
<div class="pattern-period">
|
|||
|
<p>历史时段: {{ formatDateRange(pattern.period) }}</p>
|
|||
|
</div>
|
|||
|
</el-collapse-item>
|
|||
|
</el-collapse>
|
|||
|
</div>
|
|||
|
</el-card>
|
|||
|
</div>
|
|||
|
</template>
|
|||
|
```
|
|||
|
|
|||
|
## 三、预测解释生成器实现 🧩
|
|||
|
|
|||
|
### 1. 解释文本生成器
|
|||
|
```python
|
|||
|
def generate_explanation_summary(predictions, explanation_data):
|
|||
|
"""
|
|||
|
根据预测结果和解释数据生成人类可读的解释摘要
|
|||
|
|
|||
|
Args:
|
|||
|
predictions: 预测结果序列
|
|||
|
explanation_data: 包含各种解释数据的字典
|
|||
|
|
|||
|
Returns:
|
|||
|
summary: 人类可读的解释摘要
|
|||
|
"""
|
|||
|
summary = []
|
|||
|
|
|||
|
# 分析预测趋势
|
|||
|
trend = analyze_trend(predictions)
|
|||
|
if trend == 'increasing':
|
|||
|
summary.append("预测显示未来销量呈上升趋势。")
|
|||
|
elif trend == 'decreasing':
|
|||
|
summary.append("预测显示未来销量呈下降趋势。")
|
|||
|
else:
|
|||
|
summary.append("预测显示未来销量相对稳定。")
|
|||
|
|
|||
|
# 添加关键影响因素解释
|
|||
|
if 'factors' in explanation_data:
|
|||
|
top_factors = explanation_data['factors'][:3] # 取前三个最重要的因素
|
|||
|
factor_text = "主要影响因素包括: "
|
|||
|
for i, (factor, data) in enumerate(top_factors):
|
|||
|
direction = "增加" if data['contribution'] > 0 else "减少"
|
|||
|
if i > 0:
|
|||
|
factor_text += "、"
|
|||
|
factor_text += f"{factor}({direction})"
|
|||
|
summary.append(factor_text)
|
|||
|
|
|||
|
# 添加异常值解释
|
|||
|
if 'anomalies' in explanation_data and explanation_data['anomalies']:
|
|||
|
anomaly_count = len(explanation_data['anomalies'])
|
|||
|
summary.append(f"预测中发现{anomaly_count}个异常值,可能需要特别关注。")
|
|||
|
|
|||
|
# 添加历史模式参考
|
|||
|
if 'similar_patterns' in explanation_data and explanation_data['similar_patterns']:
|
|||
|
top_pattern = explanation_data['similar_patterns'][0]
|
|||
|
similarity = top_pattern['similarity'] * 100
|
|||
|
summary.append(f"当前预测模式与历史数据中的某些时段有{similarity:.1f}%的相似度,可参考历史表现。")
|
|||
|
|
|||
|
# 生成建议
|
|||
|
recommendations = generate_recommendations(predictions, explanation_data)
|
|||
|
if recommendations:
|
|||
|
summary.append("建议: " + recommendations)
|
|||
|
|
|||
|
return " ".join(summary)
|
|||
|
```
|
|||
|
|
|||
|
### 2. 特定场景解释生成
|
|||
|
```python
|
|||
|
def generate_anomaly_explanation(value, z_score, day_index):
|
|||
|
"""
|
|||
|
为异常值生成解释
|
|||
|
|
|||
|
Args:
|
|||
|
value: 异常预测值
|
|||
|
z_score: Z分数(标准差倍数)
|
|||
|
day_index: 异常值所在的天数索引
|
|||
|
|
|||
|
Returns:
|
|||
|
explanation: 异常值解释文本
|
|||
|
"""
|
|||
|
weekday = (datetime.now() + timedelta(days=day_index)).strftime("%A")
|
|||
|
|
|||
|
if z_score > 0:
|
|||
|
if weekday in ['Saturday', 'Sunday']:
|
|||
|
return f"该值异常偏高,可能与周末效应有关。周末通常客流量增加,销量上升。"
|
|||
|
else:
|
|||
|
return f"该值异常偏高,可能受到促销活动、季节性因素或特殊事件影响。"
|
|||
|
else:
|
|||
|
if weekday in ['Saturday', 'Sunday']:
|
|||
|
return f"该值在周末异常偏低,与典型周末销售模式不符,可能有特殊原因导致客流减少。"
|
|||
|
else:
|
|||
|
return f"该值异常偏低,可能受到库存问题、竞争对手活动或外部因素影响。"
|
|||
|
```
|
|||
|
|
|||
|
### 3. 建议生成器
|
|||
|
```python
|
|||
|
def generate_recommendations(predictions, explanation_data):
|
|||
|
"""
|
|||
|
基于预测结果和解释数据生成行动建议
|
|||
|
|
|||
|
Args:
|
|||
|
predictions: 预测结果序列
|
|||
|
explanation_data: 解释数据字典
|
|||
|
|
|||
|
Returns:
|
|||
|
recommendations: 建议文本
|
|||
|
"""
|
|||
|
recommendations = []
|
|||
|
|
|||
|
# 分析预测趋势
|
|||
|
trend = analyze_trend(predictions)
|
|||
|
|
|||
|
# 基于趋势的库存建议
|
|||
|
if trend == 'increasing':
|
|||
|
recommendations.append("考虑增加采购量,确保库存充足")
|
|||
|
elif trend == 'decreasing':
|
|||
|
recommendations.append("考虑减少采购,避免库存积压")
|
|||
|
|
|||
|
# 基于异常值的建议
|
|||
|
if 'anomalies' in explanation_data and explanation_data['anomalies']:
|
|||
|
high_anomalies = [a for a in explanation_data['anomalies'] if a['severity'] == 'high']
|
|||
|
if high_anomalies:
|
|||
|
recommendations.append("关注高度异常的预测日期,制定应对预案")
|
|||
|
|
|||
|
# 基于特征重要性的建议
|
|||
|
if 'factors' in explanation_data:
|
|||
|
weather_factors = [f for f, _ in explanation_data['factors'] if 'temperature' in f or 'weather' in f]
|
|||
|
if weather_factors:
|
|||
|
recommendations.append("密切关注天气变化对销量的影响")
|
|||
|
|
|||
|
promotion_factors = [f for f, _ in explanation_data['factors'] if 'promotion' in f]
|
|||
|
if promotion_factors:
|
|||
|
recommendations.append("促销活动对销量影响显著,可考虑优化促销策略")
|
|||
|
|
|||
|
return ",".join(recommendations) + "。" if recommendations else ""
|
|||
|
```
|
|||
|
|
|||
|
## 四、实施与集成方案 🔧
|
|||
|
|
|||
|
### 1. 系统集成步骤
|
|||
|
1. **后端API实现**:
|
|||
|
- 在`pharmacy_predictor.py`中添加预测解释相关函数
|
|||
|
- 在`api.py`中添加新的API端点
|
|||
|
|
|||
|
2. **数据存储扩展**:
|
|||
|
- 添加特征重要性存储
|
|||
|
- 保存历史预测与实际销量对比数据
|
|||
|
|
|||
|
3. **前端集成**:
|
|||
|
- 在`UI/src/views/PredictionView.vue`中添加解释面板组件
|
|||
|
- 添加可视化图表展示影响因素
|
|||
|
|
|||
|
### 2. 代码实现示例
|
|||
|
|
|||
|
#### A. 后端实现
|
|||
|
```python
|
|||
|
# 在pharmacy_predictor.py中添加
|
|||
|
|
|||
|
def explain_model_prediction(product_id, model_type, predictions, features):
|
|||
|
"""
|
|||
|
为模型预测结果提供解释
|
|||
|
"""
|
|||
|
# 加载模型
|
|||
|
model_path = get_model_path(product_id, model_type)
|
|||
|
model = torch.load(model_path)
|
|||
|
|
|||
|
# 获取特征重要性
|
|||
|
feature_names = ['sales', 'price', 'weekday', 'month', 'is_holiday',
|
|||
|
'is_weekend', 'is_promotion', 'temperature']
|
|||
|
feature_importance = analyze_feature_importance(model, features, feature_names)
|
|||
|
|
|||
|
# 获取历史数据
|
|||
|
historical_data = load_historical_sales_data(product_id)
|
|||
|
|
|||
|
# 生成解释
|
|||
|
explanation = {
|
|||
|
'feature_importance': feature_importance,
|
|||
|
'similar_patterns': find_similar_historical_patterns(predictions, historical_data),
|
|||
|
'anomalies': detect_and_explain_anomalies(predictions, calculate_historical_stats(historical_data))
|
|||
|
}
|
|||
|
|
|||
|
# 生成总结
|
|||
|
explanation['summary'] = generate_explanation_summary(predictions, explanation)
|
|||
|
|
|||
|
return explanation
|
|||
|
```
|
|||
|
|
|||
|
#### B. API端点实现
|
|||
|
```python
|
|||
|
# 在api.py中添加
|
|||
|
|
|||
|
@app.route('/api/prediction/explain', methods=['POST'])
|
|||
|
def explain_prediction():
|
|||
|
"""
|
|||
|
提供预测结果的详细解释
|
|||
|
"""
|
|||
|
try:
|
|||
|
data = request.json
|
|||
|
product_id = data.get('product_id')
|
|||
|
model_type = data.get('model_type')
|
|||
|
future_days = data.get('future_days', 7)
|
|||
|
|
|||
|
# 验证参数
|
|||
|
if not product_id or not model_type:
|
|||
|
return jsonify({"status": "error", "error": "缺少必要参数"}), 400
|
|||
|
|
|||
|
# 获取预测结果和特征
|
|||
|
predictions, features = load_model_and_predict_with_features(
|
|||
|
product_id, model_type, future_days
|
|||
|
)
|
|||
|
|
|||
|
# 生成解释
|
|||
|
explanation = explain_model_prediction(
|
|||
|
product_id, model_type, predictions, features
|
|||
|
)
|
|||
|
|
|||
|
return jsonify({
|
|||
|
"status": "success",
|
|||
|
"product_id": product_id,
|
|||
|
"model_type": model_type,
|
|||
|
"predictions": predictions.tolist(),
|
|||
|
"explanation": explanation
|
|||
|
})
|
|||
|
|
|||
|
except Exception as e:
|
|||
|
return jsonify({"status": "error", "error": str(e)}), 500
|
|||
|
```
|
|||
|
|
|||
|
### 3. UI实现示例
|
|||
|
```vue
|
|||
|
<!-- 在PredictionView.vue中添加 -->
|
|||
|
<template>
|
|||
|
<div>
|
|||
|
<!-- 现有预测结果展示 -->
|
|||
|
<div class="prediction-results">
|
|||
|
<!-- ... 现有代码 ... -->
|
|||
|
</div>
|
|||
|
|
|||
|
<!-- 新增预测解释面板 -->
|
|||
|
<el-collapse v-if="predictionExplanation">
|
|||
|
<el-collapse-item title="预测结果解释" name="explanation">
|
|||
|
<div class="explanation-summary">
|
|||
|
<el-alert
|
|||
|
:title="predictionExplanation.summary"
|
|||
|
type="info"
|
|||
|
:closable="false"
|
|||
|
show-icon
|
|||
|
></el-alert>
|
|||
|
</div>
|
|||
|
|
|||
|
<!-- 关键影响因素 -->
|
|||
|
<div class="key-factors-section">
|
|||
|
<h4>关键影响因素</h4>
|
|||
|
<el-table
|
|||
|
:data="keyFactors"
|
|||
|
style="width: 100%"
|
|||
|
>
|
|||
|
<el-table-column prop="factor" label="因素名称"></el-table-column>
|
|||
|
<el-table-column prop="importance" label="重要性">
|
|||
|
<template slot-scope="scope">
|
|||
|
<el-progress :percentage="scope.row.importance * 100"></el-progress>
|
|||
|
</template>
|
|||
|
</el-table-column>
|
|||
|
<el-table-column prop="impact" label="影响方向">
|
|||
|
<template slot-scope="scope">
|
|||
|
<span :class="scope.row.impact > 0 ? 'positive-impact' : 'negative-impact'">
|
|||
|
{{ scope.row.impact > 0 ? '正面影响' : '负面影响' }}
|
|||
|
</span>
|
|||
|
</template>
|
|||
|
</el-table-column>
|
|||
|
</el-table>
|
|||
|
</div>
|
|||
|
|
|||
|
<!-- 异常值检测 -->
|
|||
|
<div v-if="predictionExplanation.anomalies && predictionExplanation.anomalies.length > 0" class="anomalies-section">
|
|||
|
<h4>异常值检测</h4>
|
|||
|
<el-card v-for="(anomaly, index) in predictionExplanation.anomalies" :key="index" class="anomaly-card">
|
|||
|
<div slot="header">
|
|||
|
<span>第{{ anomaly.day + 1 }}天异常: {{ anomaly.value }}</span>
|
|||
|
</div>
|
|||
|
<p>{{ anomaly.explanation }}</p>
|
|||
|
</el-card>
|
|||
|
</div>
|
|||
|
|
|||
|
<!-- 相似历史模式 -->
|
|||
|
<div v-if="predictionExplanation.similar_patterns && predictionExplanation.similar_patterns.length > 0" class="similar-patterns-section">
|
|||
|
<h4>相似历史模式</h4>
|
|||
|
<el-tabs>
|
|||
|
<el-tab-pane
|
|||
|
v-for="(pattern, index) in predictionExplanation.similar_patterns.slice(0, 3)"
|
|||
|
:key="index"
|
|||
|
:label="`模式 ${index + 1} (相似度: ${(pattern.similarity * 100).toFixed(1)}%)`"
|
|||
|
>
|
|||
|
<div class="pattern-chart">
|
|||
|
<line-chart :chart-data="getPatternChartData(pattern)"></line-chart>
|
|||
|
</div>
|
|||
|
</el-tab-pane>
|
|||
|
</el-tabs>
|
|||
|
</div>
|
|||
|
</el-collapse-item>
|
|||
|
</el-collapse>
|
|||
|
</div>
|
|||
|
</template>
|
|||
|
|
|||
|
<script>
|
|||
|
export default {
|
|||
|
// ... 现有代码 ...
|
|||
|
|
|||
|
data() {
|
|||
|
return {
|
|||
|
// ... 现有数据 ...
|
|||
|
predictionExplanation: null,
|
|||
|
keyFactors: []
|
|||
|
};
|
|||
|
},
|
|||
|
|
|||
|
methods: {
|
|||
|
// ... 现有方法 ...
|
|||
|
|
|||
|
async getPrediction() {
|
|||
|
// 获取预测结果
|
|||
|
const response = await this.fetchPrediction();
|
|||
|
|
|||
|
// 获取预测解释
|
|||
|
this.fetchPredictionExplanation();
|
|||
|
},
|
|||
|
|
|||
|
async fetchPredictionExplanation() {
|
|||
|
try {
|
|||
|
const response = await fetch('/api/prediction/explain', {
|
|||
|
method: 'POST',
|
|||
|
headers: {
|
|||
|
'Content-Type': 'application/json'
|
|||
|
},
|
|||
|
body: JSON.stringify({
|
|||
|
product_id: this.form.product_id,
|
|||
|
model_type: this.form.model_type,
|
|||
|
future_days: this.form.future_days
|
|||
|
})
|
|||
|
});
|
|||
|
|
|||
|
const data = await response.json();
|
|||
|
|
|||
|
if (data.status === 'success') {
|
|||
|
this.predictionExplanation = data.explanation;
|
|||
|
this.keyFactors = this.formatKeyFactors(data.explanation.feature_importance);
|
|||
|
}
|
|||
|
} catch (error) {
|
|||
|
console.error('获取预测解释失败:', error);
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
formatKeyFactors(featureImportance) {
|
|||
|
// 将特征重要性数据转换为表格数据
|
|||
|
return Object.entries(featureImportance)
|
|||
|
.map(([factor, value]) => ({
|
|||
|
factor,
|
|||
|
importance: Math.abs(value),
|
|||
|
impact: value
|
|||
|
}))
|
|||
|
.sort((a, b) => b.importance - a.importance)
|
|||
|
.slice(0, 5); // 只显示前5个最重要的因素
|
|||
|
},
|
|||
|
|
|||
|
getPatternChartData(pattern) {
|
|||
|
// 准备图表数据
|
|||
|
return {
|
|||
|
labels: Array.from({length: pattern.data.length}, (_, i) => `Day ${i+1}`),
|
|||
|
datasets: [{
|
|||
|
label: '历史销量',
|
|||
|
data: pattern.data,
|
|||
|
borderColor: '#409EFF',
|
|||
|
fill: false
|
|||
|
}]
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
</script>
|
|||
|
```
|
|||
|
|
|||
|
## 五、应用场景与优势 🌟
|
|||
|
|
|||
|
### 1. 应用场景
|
|||
|
- **库存管理决策支持**:解释预测结果背后的原因,帮助制定更精准的库存计划
|
|||
|
- **销售策略优化**:理解影响销量的关键因素,优化促销和定价策略
|
|||
|
- **异常情况预警**:提前识别可能的销售异常,制定应对措施
|
|||
|
- **多模型比较分析**:解释不同模型预测结果的差异原因,选择最适合的模型
|
|||
|
|
|||
|
### 2. 系统优势
|
|||
|
- **提高可解释性**:将"黑盒"模型转变为可理解的决策支持工具
|
|||
|
- **增强用户信任**:通过解释预测背后的逻辑,增强用户对预测结果的信任
|
|||
|
- **辅助决策制定**:提供数据支持的建议,帮助用户做出更明智的决策
|
|||
|
- **持续学习优化**:通过解释系统,识别模型的不足和改进方向
|
|||
|
|
|||
|
### 3. 未来扩展方向
|
|||
|
- **交互式解释**:允许用户通过调整输入参数,实时观察对预测结果的影响
|
|||
|
- **场景模拟**:基于不同假设条件(如天气变化、促销力度)模拟预测结果
|
|||
|
- **自动化建议系统**:根据预测解释自动生成库存管理和销售策略建议
|
|||
|
- **多维度可视化**:提供更丰富的可视化工具,展示预测结果与各因素的关系
|
|||
|
</rewritten_file>
|