java案例如何利用历史大数据建模预测?

wen java案例 2

我来给你一个完整的Java大数据预测建模实战案例,我会用时间序列预测机器学习两个维度来展示。

java案例如何利用历史大数据建模预测?

📊 案例:电商销售预测系统

整体架构设计

graph TD
    A[历史数据源] --> B[数据清洗/特征工程]
    B --> C[模型训练]
    C --> D[模型评估]
    D --> E[模型部署]
    E --> F[实时预测]
    F --> G[预测结果可视化]

核心实现代码

1 数据准备与特征工程

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
// 特征工程类
public class FeatureEngineering {
    // 数据实体
    static class SalesRecord {
        LocalDate date;
        double sales;
        String productId;
        String category;
        double price;
        int quantity;
        String promotion; // 是否有促销
        int weatherScore; // 天气影响指数
        boolean isHoliday; // 是否节假日
        // constructor, getters/setters...
    }
    // 特征提取器
    public static List<Map<String, Object>> extractFeatures(List<SalesRecord> records) {
        List<Map<String, Object>> features = new ArrayList<>();
        for (SalesRecord record : records) {
            Map<String, Object> featureMap = new HashMap<>();
            // 1. 时间特征
            LocalDate date = record.date;
            featureMap.put("dayOfWeek", date.getDayOfWeek().getValue());
            featureMap.put("month", date.getMonthValue());
            featureMap.put("isWeekend", date.getDayOfWeek().getValue() > 5);
            featureMap.put("dayOfMonth", date.getDayOfMonth());
            // 2. 历史统计特征(滑动窗口)
            featureMap.put("ma7", calculateMovingAverage(records, date, 7, record.productId));
            featureMap.put("ma30", calculateMovingAverage(records, date, 30, record.productId));
            featureMap.put("salesLag1", getPreviousDaysSales(records, date, 1, record.productId));
            featureMap.put("salesLag7", getPreviousDaysSales(records, date, 7, record.productId));
            // 3. 业务特征
            featureMap.put("price", record.price);
            featureMap.put("promotion", record.promotion.equals("Y") ? 1 : 0);
            featureMap.put("weatherScore", record.weatherScore);
            featureMap.put("isHoliday", record.isHoliday ? 1 : 0);
            // 4. 分类特征
            featureMap.put("category", record.category);
            features.add(featureMap);
        }
        return features;
    }
    // 计算移动平均
    private static double calculateMovingAverage(List<SalesRecord> records, 
            LocalDate date, int window, String productId) {
        List<SalesRecord> pastRecords = records.stream()
            .filter(r -> r.productId.equals(productId))
            .filter(r -> r.date.isBefore(date))
            .limit(window)
            .collect(Collectors.toList());
        return pastRecords.stream()
            .mapToDouble(r -> r.sales)
            .average()
            .orElse(0);
    }
    // 获取前一天销量
    private static double getPreviousDaysSales(List<SalesRecord> records, 
            LocalDate date, int lag, String productId) {
        return records.stream()
            .filter(r -> r.productId.equals(productId))
            .filter(r -> r.date.equals(date.minusDays(lag)))
            .mapToDouble(r -> r.sales)
            .findFirst()
            .orElse(0);
    }
}

2 模型训练(集成LightGBM)

import com.microsoft.ml.lightgbm.*;
import java.io.*;
// 使用LightGBM进行预测
public class SalesPredictor {
    private Booster booster;
    // 训练模型
    public void trainModel(List<Map<String, Object>> features, 
                          List<Double> labels) throws Exception {
        // 转换为LightGBM需要的数据格式
        Dataset data = createDataset(features, labels);
        // 设置训练参数
        Map<String, String> params = new HashMap<>();
        params.put("objective", "regression");
        params.put("metric", "rmse");
        params.put("learning_rate", "0.05");
        params.put("num_leaves", "31");
        params.put("feature_fraction", "0.8");
        params.put("bagging_fraction", "0.8");
        params.put("bagging_freq", "5");
        params.put("num_iterations", "200");
        params.put("early_stopping_round", "50");
        // 创建Booster
        booster = new Booster(params, data);
        // 训练
        booster.train();
        System.out.println("Model trained successfully!");
    }
    // 数据转换
    private Dataset createDataset(List<Map<String, Object>> features, 
                                 List<Double> labels) throws Exception {
        // 特征名称映射
        String[] featureNames = {
            "dayOfWeek", "month", "isWeekend", "dayOfMonth",
            "ma7", "ma30", "salesLag1", "salesLag7",
            "price", "promotion", "weatherScore", "isHoliday"
        };
        // 构造浮点特征矩阵
        double[][] featureValues = new double[features.size()][featureNames.length];
        for (int i = 0; i < features.size(); i++) {
            Map<String, Object> feature = features.get(i);
            for (int j = 0; j < featureNames.length; j++) {
                Object value = feature.get(featureNames[j]);
                featureValues[i][j] = value instanceof Number ? 
                    ((Number) value).doubleValue() : 0;
            }
        }
        // 创建Dataset
        Dataset dataset = new Dataset(featureValues, featureNames.length);
        dataset.setLabel(labels.stream().mapToDouble(d -> d).toArray());
        return dataset;
    }
    // 预测单个样本
    public double predict(Map<String, Object> features) {
        // 转换特征为double数组
        int[] colIdx = {0,1,2,3,4,5,6,7,8,9,10,11};
        double[] rowValues = new double[colIdx.length];
        String[] featureNames = {
            "dayOfWeek", "month", "isWeekend", "dayOfMonth",
            "ma7", "ma30", "salesLag1", "salesLag7",
            "price", "promotion", "weatherScore", "isHoliday"
        };
        for (int i = 0; i < featureNames.length; i++) {
            Object value = features.get(featureNames[i]);
            rowValues[i] = value instanceof Number ? 
                ((Number) value).doubleValue() : 0;
        }
        double[] prediction = booster.predict(rowValues, 1);
        return prediction[0];
    }
    // 批量预测
    public List<Double> predictBatch(List<Map<String, Object>> features) {
        return features.stream()
            .map(this::predict)
            .collect(Collectors.toList());
    }
    // 模型保存
    public void saveModel(String filePath) throws IOException {
        booster.saveModel(filePath);
    }
    // 模型加载
    public void loadModel(String filePath) throws IOException {
        booster = Booster.loadModel(filePath);
    }
}

3 预测调度与结果处理

import java.util.concurrent.*;
import java.util.stream.*;
public class PredictionEngine {
    private SalesPredictor predictor;
    // 每日预测任务
    public Map<String, Double> predictDailySales(LocalDate targetDate, 
                                                List<SalesRecord> historyData) {
        // 生成每日预测特征
        List<Map<String, Object>> features = generatePredictionFeatures(targetDate, historyData);
        // 执行预测
        Map<String, Double> predictions = new HashMap<>();
        for (Map.Entry<String, List<Map<String, Object>>> entry : 
                groupByProduct(features).entrySet()) {
            String productId = entry.getKey();
            List<Map<String, Object>> productFeatures = entry.getValue();
            // 批量预测
            List<Double> results = predictor.predictBatch(productFeatures);
            predictions.put(productId, results.get(0));
        }
        return predictions;
    }
    // 未来7天预测
    public Map<LocalDate, Map<String, Double>> predictWeekly(LocalDate startDate,
                                                            List<SalesRecord> history) {
        Map<LocalDate, Map<String, Double>> weeklyPredictions = new HashMap<>();
        for (int i = 0; i < 7; i++) {
            LocalDate date = startDate.plusDays(i);
            Map<String, Double> dailyPredictions = predictDailySales(date, history);
            weeklyPredictions.put(date, dailyPredictions);
            // 预测后更新历史数据,用于下一步预测
            history = addPredictedRecords(history, date, dailyPredictions);
        }
        return weeklyPredictions;
    }
    // 特征生成
    private List<Map<String, Object>> generatePredictionFeatures(LocalDate date, 
                                                                List<SalesRecord> history) {
        List<Map<String, Object>> features = new ArrayList<>();
        // 获取所有商品
        Set<String> products = history.stream()
            .map(r -> r.productId)
            .collect(Collectors.toSet());
        for (String productId : products) {
            Map<String, Object> feature = new HashMap<>();
            // 基础特征
            feature.put("dayOfWeek", date.getDayOfWeek().getValue());
            feature.put("month", date.getMonthValue());
            feature.put("isWeekend", date.getDayOfWeek().getValue() > 5);
            feature.put("dayOfMonth", date.getDayOfMonth());
            // 历史统计特征
            String finalProductId = productId;
            List<SalesRecord> productHistory = history.stream()
                .filter(r -> r.productId.equals(finalProductId))
                .collect(Collectors.toList());
            // 填充历史特征
            // ... 类似前面特征工程的方法
            features.add(feature);
        }
        return features;
    }
    // 按商品分组
    private Map<String, List<Map<String, Object>>> groupByProduct(
            List<Map<String, Object>> features) {
        return features.stream()
            .collect(Collectors.groupingBy(f -> f.get("productId").toString()));
    }
    // 预测结果缓存
    private Map<String, Map<LocalDate, Double>> predictionCache = new ConcurrentHashMap<>();
    public void cachePrediction(String productId, LocalDate date, double value) {
        predictionCache
            .computeIfAbsent(productId, k -> new HashMap<>())
            .put(date, value);
    }
    public Double getCachedPrediction(String productId, LocalDate date) {
        return predictionCache
            .getOrDefault(productId, Collections.emptyMap())
            .get(date);
    }
}

4 预测效果评估

public class ModelEvaluator {
    public static class EvaluationResult {
        double rmse;
        double mae;
        double mape;
        double r2;
        @Override
        public String toString() {
            return String.format(
                "RMSE: %.2f | MAE: %.2f | MAPE: %.2f%% | R²: %.4f", 
                rmse, mae, mape, r2);
        }
    }
    // 评估预测效果
    public static EvaluationResult evaluate(List<Double> actual, List<Double> predicted) {
        EvaluationResult result = new EvaluationResult();
        // RMSE
        double sumSquaredError = 0;
        // MAE
        double sumAbsError = 0;
        // MAPE
        double sumPercentageError = 0;
        // R²
        double meanActual = actual.stream().mapToDouble(Double::doubleValue).average().orElse(0);
        double sumSquaredTotal = 0;
        for (int i = 0; i < actual.size(); i++) {
            double error = actual.get(i) - predicted.get(i);
            sumSquaredError += error * error;
            sumAbsError += Math.abs(error);
            sumPercentageError += Math.abs(error / actual.get(i)) * 100;
            sumSquaredTotal += Math.pow(actual.get(i) - meanActual, 2);
        }
        int n = actual.size();
        result.rmse = Math.sqrt(sumSquaredError / n);
        result.mae = sumAbsError / n;
        result.mape = sumPercentageError / n;
        result.r2 = 1 - (sumSquaredError / sumSquaredTotal);
        return result;
    }
    // K倍交叉验证
    public static List<EvaluationResult> crossValidation(List<SalesRecord> data,
                                                        int k) {
        List<EvaluationResult> results = new ArrayList<>();
        Collections.shuffle(data);
        int foldSize = data.size() / k;
        for (int i = 0; i < k; i++) {
            List<SalesRecord> trainData = new ArrayList<>(
                data.subList(0, i * foldSize));
            trainData.addAll(data.subList((i + 1) * foldSize, data.size()));
            List<SalesRecord> testData = new ArrayList<>(
                data.subList(i * foldSize, (i + 1) * foldSize));
            // 训练模型
            // ... 这里省略训练代码
            // 预测
            List<Double> predictions = new ArrayList<>();
            List<Double> actuals = testData.stream()
                .map(SalesRecord::getSales)
                .collect(Collectors.toList());
            // 评估
            EvaluationResult evalResult = evaluate(actuals, predictions);
            results.add(evalResult);
            System.out.println("Fold " + (i + 1) + ": " + evalResult);
        }
        return results;
    }
}

实际应用示例

public class DemandForecastingApp {
    public static void main(String[] args) throws Exception {
        // 1. 加载历史数据
        List<SalesRecord> historicalData = loadHistoricalData("sales_2020_2023.csv");
        // 2. 特征工程
        List<Map<String, Object>> features = FeatureEngineering.extractFeatures(historicalData);
        List<Double> labels = historicalData.stream()
            .map(SalesRecord::getSales)
            .collect(Collectors.toList());
        // 3. 训练模型
        SalesPredictor predictor = new SalesPredictor();
        predictor.trainModel(features, labels);
        // 4. 模型评估
        List<EvaluationResult> cvResults = ModelEvaluator.crossValidation(historicalData, 5);
        System.out.println("交叉验证结果: " + cvResults);
        // 5. 预测未来7天销量
        PredictionEngine engine = new PredictionEngine();
        LocalDate startDate = LocalDate.now().plusDays(1);
        Map<LocalDate, Map<String, Double>> predictions = 
            engine.predictWeekly(startDate, historicalData);
        // 6. 输出预测结果
        predictions.forEach((date, productPredictions) -> {
            System.out.println("\n📅 日期: " + date);
            productPredictions.forEach((product, sales) -> {
                System.out.printf(" 商品 %s: %.2f 件%n", product, sales);
            });
        });
        // 7. 保存模型
        predictor.saveModel("sales_prediction_model.txt");
    }
    private static List<SalesRecord> loadHistoricalData(String filePath) {
        // 从CSV加载数据
        return new ArrayList<>();
    }
}

生产环境部署要点

# Docker部署配置
version: '3.8'
services:
  prediction-service:
    build: .
    ports:
      - "8081:8080"
    environment:
      - MODEL_PATH=/models/sales_model.txt
      - DATA_RETENTION_DAYS=365
    resources:
      memory: 4G
      cpus: '4'
  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
// 实时特征计算微服务
@RestController
@RequestMapping("/api/prediction")
public class PredictionController {
    @Autowired
    private PredictionEngine engine;
    @GetMapping("/daily")
    public ApiResponse predictDaily(@RequestParam LocalDate date) {
        List<SalesRecord> history = loadRecentHistory();
        Map<String, Double> predictions = engine.predictDailySales(date, history);
        return ApiResponse.success(predictions);
    }
    @GetMapping("/weekly")
    public ApiResponse predictWeekly(@RequestParam LocalDate startDate) {
        List<SalesRecord> history = loadRecentHistory();
        Map<LocalDate, Map<String, Double>> predictions = 
            engine.predictWeekly(startDate, history);
        return ApiResponse.success(predictions);
    }
}

预测效果优化建议

优化方向 方法 预期效果
特征工程 增加节假日、天气、活动等外部特征 准确率提升5-10%
模型选择 使用AutoML对比算法(XGBoost、Prophet) 寻找最优模型
异常处理 检测销售异常(促销、断货)并修正 减少极端值影响
增量学习 每月增量训练,使用最新数据 适应市场变化
集成学习 多个模型融合(LightGBM + Prophet) 稳定性提升

这个案例涵盖了从数据处理、特征工程、模型训练到预测的完整流程,实际应用中可以根据业务需求调整特征和模型参数,关键是特征工程要贴合业务逻辑,这样才能最大化模型预测效果。

抱歉,评论功能暂时关闭!