Python项目--基于机器学习的股票预测分析系统
1. 项目介绍
在当今数字化时代,金融市场的数据分析和预测已经成为投资决策的重要依据。本文将详细介绍一个基于Python的股票预测分析系统,该系统利用机器学习算法对历史股票数据进行分析,并预测未来股票价格走势,为投资者提供决策支持。
1.1 项目背景
股票市场充满不确定性,传统的技术分析和基本面分析方法往往依赖于人为判断,存在主观性强、效率低等问题。随着机器学习技术的发展,利用算法对海量历史数据进行分析,挖掘其中的规律和模式,已经成为可能。本项目旨在构建一个完整的股票预测分析系统,集成数据采集、预处理、特征工程、模型训练与评估、预测可视化等功能,为投资决策提供科学依据。
1.2 项目目标
- 构建一个完整的股票数据采集与预处理流程
- 实现多种机器学习模型用于股票价格预测
- 提供直观的数据可视化和分析工具
- 开发用户友好的接口,便于投资者使用
- 评估不同模型的预测性能,提供最优预测结果
1.3 技术栈
- 编程语言:Python 3.8+
- 数据处理:Pandas, NumPy
- 机器学习框架:Scikit-learn, TensorFlow, Keras
- 深度学习模型:LSTM, GRU, Transformer
- 数据可视化:Matplotlib, Seaborn, Plotly
- Web接口:Flask, Streamlit
- 数据存储:SQLite, MongoDB
- API调用:yfinance, alpha_vantage
2. 系统架构
本系统采用模块化设计,包含以下核心组件:
2.1 系统架构图
+------------------------+ +------------------------+ +------------------------+
| | | | | |
| 数据采集模块 | | 数据预处理模块 | | 特征工程模块 |
| | | | | |
+------------------------+ +------------------------+ +------------------------+| | |v v v
+------------------------+ +------------------------+ +------------------------+
| | | | | |
| 模型训练模块 | <- | 特征选择模块 | <- | 数据存储模块 |
| | | | | |
+------------------------+ +------------------------+ +------------------------+| ^ ^v | |
+------------------------+ +------------------------+ +------------------------+
| | | | | |
| 预测评估模块 | -> | 结果可视化模块 | -> | 用户接口模块 |
| | | | | |
+------------------------+ +------------------------+ +------------------------+
2.2 模块功能说明
- 数据采集模块:负责从各种数据源获取股票历史数据,包括价格、交易量、财务指标等
- 数据预处理模块:对原始数据进行清洗、标准化、去噪等处理
- 特征工程模块:构建预测模型所需的特征,包括技术指标、统计特征等
- 数据存储模块:将处理后的数据存储到数据库中,便于后续分析
- 特征选择模块:从众多特征中选择最具预测能力的特征子集
- 模型训练模块:实现多种机器学习算法,训练预测模型
- 预测评估模块:评估模型性能,生成预测结果
- 结果可视化模块:将预测结果以图表形式展示
- 用户接口模块:提供友好的用户界面,便于用户操作和查看结果
3. 数据采集与预处理
3.1 数据来源
本系统支持多种数据来源,主要包括:
-
公开API:
- Yahoo Finance (yfinance)
- Alpha Vantage
- Quandl
- Tushare (针对中国股市)
-
CSV文件导入:支持用户上传自定义格式的CSV文件
-
数据库导入:支持从SQLite、MongoDB等数据库导入数据
3.2 数据采集实现
以下是使用yfinance库获取股票数据的示例代码:
import yfinance as yf
import pandas as pd
from datetime import datetime, timedeltaclass StockDataCollector:def __init__(self):self.data = Nonedef collect_data(self, ticker, start_date, end_date=None, interval='1d'):"""从Yahoo Finance获取股票历史数据参数:ticker (str): 股票代码,如'AAPL'、'MSFT'start_date (str): 起始日期,格式'YYYY-MM-DD'end_date (str): 结束日期,格式'YYYY-MM-DD',默认为当前日期interval (str): 数据间隔,可选'1d'(日),'1wk'(周),'1mo'(月)返回:pandas.DataFrame: 包含股票历史数据的DataFrame"""if end_date is None:end_date = datetime.now().strftime('%Y-%m-%d')try:stock = yf.Ticker(ticker)self.data = stock.history(start=start_date, end=end_date, interval=interval)print(f"成功获取{ticker}从{start_date}到{end_date}的历史数据")return self.dataexcept Exception as e:print(f"获取数据时出错: {e}")return Nonedef save_to_csv(self, file_path):"""将数据保存为CSV文件"""if self.data is not None:self.data.to_csv(file_path)print(f"数据已保存至{file_path}")else:print("没有数据可保存")def get_stock_info(self, ticker):"""获取股票基本信息"""try:stock = yf.Ticker(ticker)info = stock.inforeturn infoexcept Exception as e:print(f"获取股票信息时出错: {e}")return None
3.3 数据预处理
原始股票数据通常包含缺失值、异常值等问题,需要进行预处理:
class StockDataPreprocessor:def __init__(self, data=None):self.data = datadef load_data(self, data):"""加载数据"""self.data = datareturn selfdef handle_missing_values(self, method='ffill'):"""处理缺失值"""if self.data is None:print("没有数据可处理")return selfif method == 'ffill':self.data = self.data.fillna(method='ffill')elif method == 'bfill':self.data = self.data.fillna(method='bfill')elif method == 'drop':self.data = self.data.dropna()elif method == 'mean':self.data = self.data.fillna(self.data.mean())return selfdef remove_outliers(self, columns, method='zscore', threshold=3):"""移除异常值"""if self.data is None:print("没有数据可处理")return selfif method == 'zscore':for col in columns:if col in self.data.columns:mean = self.data[col].mean()std = self.data[col].std()self.data = self.data[(self.data[col] - mean).abs() <= threshold * std]return selfdef normalize_data(self, columns, method='minmax'):"""数据标准化"""if self.data is None:print("没有数据可处理")return selfif method == 'minmax':for col in columns:if col in self.data.columns:min_val = self.data[col].min()max_val = self.data[col].max()self.data[col] = (self.data[col] - min_val) / (max_val - min_val)elif method == 'zscore':for col in columns:if col in self.data.columns:mean = self.data[col].mean()std = self.data[col].std()self.data[col] = (self.data[col] - mean) / stdreturn selfdef get_processed_data(self):"""获取处理后的数据"""return self.data## 4. 特征工程特征工程是机器学习模型性能的关键决定因素。在股票预测中,我们需要从原始价格数据中提取有价值的特征。### 4.1 技术指标计算技术指标是股票分析中常用的工具,可以揭示价格趋势、动量和波动性等信息:```python
import numpy as np
import pandas as pd
import talibclass TechnicalIndicators:def __init__(self, data=None):self.data = datadef load_data(self, data):"""加载数据"""self.data = datareturn selfdef add_moving_averages(self, periods=[5, 10, 20, 50, 200]):"""添加移动平均线"""if self.data is None or 'Close' not in self.data.columns:print("数据不包含收盘价")return selffor period in periods:self.data[f'MA_{period}'] = self.data['Close'].rolling(window=period).mean()return selfdef add_exponential_moving_averages(self, periods=[5, 10, 20, 50, 200]):"""添加指数移动平均线"""if self.data is None or 'Close' not in self.data.columns:print("数据不包含收盘价")return selffor period in periods:self.data[f'EMA_{period}'] = self.data['Close'].ewm(span=period, adjust=False).mean()return selfdef add_rsi(self, periods=[14]):"""添加相对强弱指标(RSI)"""if self.data is None or 'Close' not in self.data.columns:print("数据不包含收盘价")return selffor period in periods:delta = self.data['Close'].diff()gain = delta.where(delta > 0, 0)loss = -delta.where(delta < 0, 0)avg_gain = gain.rolling(window=period).mean()avg_loss = loss.rolling(window=period).mean()rs = avg_gain / avg_lossself.data[f'RSI_{period}'] = 100 - (100 / (1 + rs))return selfdef add_macd(self, fast_period=12, slow_period=26, signal_period=9):"""添加MACD指标"""if self.data is None or 'Close' not in self.data.columns:print("数据不包含收盘价")return selfema_fast = self.data['Close'].ewm(span=fast_period, adjust=False).mean()ema_slow = self.data['Close'].ewm(span=slow_period, adjust=False).mean()self.data['MACD'] = ema_fast - ema_slowself.data['MACD_Signal'] = self.data['MACD'].ewm(span=signal_period, adjust=False).mean()self.data['MACD_Hist'] = self.data['MACD'] - self.data['MACD_Signal']return selfdef add_bollinger_bands(self, period=20, std_dev=2):"""添加布林带指标"""if self.data is None or 'Close' not in self.data.columns:print("数据不包含收盘价")return selfself.data[f'BB_Middle_{period}'] = self.data['Close'].rolling(window=period).mean()self.data[f'BB_Std_{period}'] = self.data['Close'].rolling(window=period).std()self.data[f'BB_Upper_{period}'] = self.data[f'BB_Middle_{period}'] + std_dev * self.data[f'BB_Std_{period}']self.data[f'BB_Lower_{period}'] = self.data[f'BB_Middle_{period}'] - std_dev * self.data[f'BB_Std_{period}']return selfdef add_atr(self, period=14):"""添加平均真实范围(ATR)指标"""if self.data is None or not all(col in self.data.columns for col in ['High', 'Low', 'Close']):print("数据不包含必要的价格列")return selfhigh_low = self.data['High'] - self.data['Low']high_close = (self.data['High'] - self.data['Close'].shift()).abs()low_close = (self.data['Low'] - self.data['Close'].shift()).abs()ranges = pd.concat([high_low, high_close, low_close], axis=1)true_range = ranges.max(axis=1)self.data[f'ATR_{period}'] = true_range.rolling(window=period).mean()return selfdef add_stochastic_oscillator(self, k_period=14, d_period=3):"""添加随机指标"""if self.data is None or not all(col in self.data.columns for col in ['High', 'Low', 'Close']):print("数据不包含必要的价格列")return selflow_min = self.data['Low'].rolling(window=k_period).min()high_max = self.data['High'].rolling(window=k_period).max()self.data['%K'] = 100 * ((self.data['Close'] - low_min) / (high_max - low_min))self.data['%D'] = self.data['%K'].rolling(window=d_period).mean()return selfdef add_obv(self):"""添加能量潮(OBV)指标"""if self.data is None or not all(col in self.data.columns for col in ['Close', 'Volume']):print("数据不包含必要的价格和成交量列")return selfobv = [0]for i in range(1, len(self.data)):if self.data['Close'].iloc[i] > self.data['Close'].iloc[i-1]:obv.append(obv[-1] + self.data['Volume'].iloc[i])elif self.data['Close'].iloc[i] < self.data['Close'].iloc[i-1]:obv.append(obv[-1] - self.data['Volume'].iloc[i])else:obv.append(obv[-1])self.data['OBV'] = obvreturn selfdef get_data_with_indicators(self):"""获取添加了技术指标的数据"""return self.data
4.2 特征选择
股票数据可能包含大量特征,但并非所有特征都对预测有帮助。特征选择可以提高模型性能并减少过拟合:
from sklearn.feature_selection import SelectKBest, f_regression, RFE
from sklearn.ensemble import RandomForestRegressorclass FeatureSelector:def __init__(self, data=None):self.data = dataself.selected_features = Nonedef load_data(self, data):"""加载数据"""self.data = datareturn selfdef prepare_data(self, target_col='Close', lag_periods=[1, 2, 3, 5, 10]):"""准备特征和目标变量,创建滞后特征"""if self.data is None:print("没有数据可处理")return None, None# 创建目标变量(下一天的收盘价)self.data['Target'] = self.data[target_col].shift(-1)# 创建滞后特征for lag in lag_periods:for col in self.data.columns:if col != 'Target':self.data[f'{col}_Lag_{lag}'] = self.data[col].shift(lag)# 删除包含NaN的行self.data = self.data.dropna()# 分离特征和目标X = self.data.drop(['Target'], axis=1)y = self.data['Target']return X, ydef select_k_best(self, X, y, k=10):"""使用F值统计量选择最佳特征"""selector = SelectKBest(score_func=f_regression, k=k)selector.fit(X, y)# 获取选中的特征cols = selector.get_support(indices=True)self.selected_features = X.columns[cols].tolist()return X[self.selected_features], self.selected_featuresdef select_with_rfe(self, X, y, n_features=10):"""使用递归特征消除法选择特征"""estimator = RandomForestRegressor(n_estimators=100, random_state=42)selector = RFE(estimator, n_features_to_select=n_features)selector.fit(X, y)# 获取选中的特征cols = selector.get_support(indices=True)self.selected_features = X.columns[cols].tolist()return X[self.selected_features], self.selected_featuresdef select_with_random_forest(self, X, y, threshold=0.01):"""使用随机森林特征重要性选择特征"""rf = RandomForestRegressor(n_estimators=100, random_state=42)rf.fit(X, y)# 获取特征重要性importances = rf.feature_importances_indices = np.argsort(importances)[::-1]# 选择重要性大于阈值的特征self.selected_features = [X.columns[i] for i in indices if importances[i] > threshold]return X[self.selected_features], self.selected_features
5. 模型实现
本系统实现了多种机器学习模型用于股票价格预测,包括传统机器学习模型和深度学习模型。
5.1 数据准备
在训练模型前,需要将数据分为训练集和测试集:
from sklearn.model_selection import train_test_split
import numpy as npclass DataPreparation:def __init__(self, X=None, y=None):self.X = Xself.y = yself.X_train = Noneself.X_test = Noneself.y_train = Noneself.y_test = Nonedef load_data(self, X, y):"""加载特征和目标数据"""self.X = Xself.y = yreturn selfdef train_test_split(self, test_size=0.2, random_state=42):"""划分训练集和测试集"""if self.X is None or self.y is None:print("没有数据可划分")return selfself.X_train, self.X_test, self.y_train, self.y_test = train_test_split(self.X, self.y, test_size=test_size, random_state=random_state, shuffle=False)return selfdef time_series_split(self, test_size=0.2):"""按时间顺序划分训练集和测试集"""if self.X is None or self.y is None:print("没有数据可划分")return self# 计算测试集大小test_index = int(len(self.X) * (1 - test_size))# 按时间顺序划分self.X_train = self.X.iloc[:test_index]self.X_test = self.X.iloc[test_index:]self.y_train = self.y.iloc[:test_index]self.y_test = self.y.iloc[test_index:]return selfdef prepare_lstm_data(self, time_steps=60):"""准备LSTM模型所需的时间序列数据"""if self.X is None or self.y is None:print("没有数据可处理")return None, None, None, None# 将数据转换为numpy数组X_values = self.X.valuesy_values = self.y.valuesX_lstm, y_lstm = [], []for i in range(time_steps, len(X_values)):X_lstm.append(X_values[i-time_steps:i])y_lstm.append(y_values[i])X_lstm, y_lstm = np.array(X_lstm), np.array(y_lstm)# 划分训练集和测试集train_size = int(len(X_lstm) * 0.8)X_train = X_lstm[:train_size]X_test = X_lstm[train_size:]y_train = y_lstm[:train_size]y_test = y_lstm[train_size:]return X_train, X_test, y_train, y_testdef get_train_test_data(self):"""获取划分后的训练集和测试集"""return self.X_train, self.X_test, self.y_train, self.y_test
5.2 传统机器学习模型
实现多种传统机器学习模型用于股票价格预测:
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.svm import SVR
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
import numpy as np
import joblibclass TraditionalModels:def __init__(self):self.models = {}self.best_model = Noneself.best_score = float('inf')def train_linear_regression(self, X_train, y_train):"""训练线性回归模型"""model = LinearRegression()model.fit(X_train, y_train)self.models['LinearRegression'] = modelreturn modeldef train_ridge_regression(self, X_train, y_train, alpha=1.0):"""训练岭回归模型"""model = Ridge(alpha=alpha)model.fit(X_train, y_train)self.models['Ridge'] = modelreturn modeldef train_lasso_regression(self, X_train, y_train, alpha=0.1):"""训练Lasso回归模型"""model = Lasso(alpha=alpha)model.fit(X_train, y_train)self.models['Lasso'] = modelreturn modeldef train_random_forest(self, X_train, y_train, n_estimators=100, max_depth=None):"""训练随机森林模型"""model = RandomForestRegressor(n_estimators=n_estimators, max_depth=max_depth, random_state=42)model.fit(X_train, y_train)self.models['RandomForest'] = modelreturn modeldef train_gradient_boosting(self, X_train, y_train, n_estimators=100, learning_rate=0.1):"""训练梯度提升树模型"""model = GradientBoostingRegressor(n_estimators=n_estimators, learning_rate=learning_rate, random_state=42)model.fit(X_train, y_train)self.models['GradientBoosting'] = modelreturn modeldef train_svr(self, X_train, y_train, kernel='rbf', C=1.0, epsilon=0.1):"""训练支持向量回归模型"""model = SVR(kernel=kernel, C=C, epsilon=epsilon)model.fit(X_train, y_train)self.models['SVR'] = modelreturn modeldef train_all_models(self, X_train, y_train):"""训练所有模型"""self.train_linear_regression(X_train, y_train)self.train_ridge_regression(X_train, y_train)self.train_lasso_regression(X_train, y_train)self.train_random_forest(X_train, y_train)self.train_gradient_boosting(X_train, y_train)self.train_svr(X_train, y_train)return self.modelsdef evaluate_model(self, model, X_test, y_test):"""评估模型性能"""y_pred = model.predict(X_test)mse = mean_squared_error(y_test, y_pred)rmse = np.sqrt(mse)mae = mean_absolute_error(y_test, y_pred)r2 = r2_score(y_test, y_pred)return {'MSE': mse,'RMSE': rmse,'MAE': mae,'R2': r2}def evaluate_all_models(self, X_test, y_test):"""评估所有模型性能"""results = {}for name, model in self.models.items():results[name] = self.evaluate_model(model, X_test, y_test)# 更新最佳模型if results[name]['RMSE'] < self.best_score:self.best_score = results[name]['RMSE']self.best_model = namereturn resultsdef save_model(self, model_name, file_path):"""保存模型"""if model_name in self.models:joblib.dump(self.models[model_name], file_path)print(f"模型已保存至{file_path}")else:print(f"模型{model_name}不存在")def load_model(self, model_name, file_path):"""加载模型"""try:model = joblib.load(file_path)self.models[model_name] = modelprint(f"模型已从{file_path}加载")return modelexcept Exception as e:print(f"加载模型时出错: {e}")return Nonedef get_best_model(self):"""获取性能最佳的模型"""if self.best_model is None:print("尚未评估模型性能")return Nonereturn self.models[self.best_model], self.best_model
5.3 深度学习模型
对于时间序列数据,深度学习模型尤其是LSTM和GRU等循环神经网络具有显著优势:
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential, load_model, Model
from tensorflow.keras.layers import Dense, LSTM, Dropout, GRU, Input, Bidirectional, Concatenate
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
from tensorflow.keras.optimizers import Adam
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as pltclass DeepLearningModels:def __init__(self):self.models = {}self.best_model = Noneself.best_score = float('inf')self.scalers = {}def preprocess_data(self, X_train, X_test, y_train, y_test, feature_range=(0, 1)):"""数据预处理,对每个特征进行标准化"""# 对特征进行标准化X_scaler = MinMaxScaler(feature_range=feature_range)X_train_scaled = X_scaler.fit_transform(X_train)X_test_scaled = X_scaler.transform(X_test)# 对目标变量进行标准化y_scaler = MinMaxScaler(feature_range=feature_range)y_train_scaled = y_scaler.fit_transform(y_train.values.reshape(-1, 1))y_test_scaled = y_scaler.transform(y_test.values.reshape(-1, 1))# 保存缩放器供后续使用self.scalers['X'] = X_scalerself.scalers['y'] = y_scalerreturn X_train_scaled, X_test_scaled, y_train_scaled, y_test_scaleddef reshape_data_for_lstm(self, X_train, X_test):"""将数据重塑为LSTM所需的形状 [samples, time_steps, features]"""# 假设每个样本只有一个时间步X_train_reshaped = X_train.reshape(X_train.shape[0], 1, X_train.shape[1])X_test_reshaped = X_test.reshape(X_test.shape[0], 1, X_test.shape[1])return X_train_reshaped, X_test_reshapeddef build_lstm_model(self, input_shape, units=50, dropout=0.2):"""构建LSTM模型"""model = Sequential()model.add(LSTM(units=units, return_sequences=True, input_shape=input_shape))model.add(Dropout(dropout))model.add(LSTM(units=units, return_sequences=False))model.add(Dropout(dropout))model.add(Dense(units=25))model.add(Dense(units=1))model.compile(optimizer=Adam(learning_rate=0.001), loss='mean_squared_error')return modeldef build_gru_model(self, input_shape, units=50, dropout=0.2):"""构建GRU模型"""model = Sequential()model.add(GRU(units=units, return_sequences=True, input_shape=input_shape))model.add(Dropout(dropout))model.add(GRU(units=units, return_sequences=False))model.add(Dropout(dropout))model.add(Dense(units=25))model.add(Dense(units=1))model.compile(optimizer=Adam(learning_rate=0.001), loss='mean_squared_error')return modeldef build_bidirectional_lstm_model(self, input_shape, units=50, dropout=0.2):"""构建双向LSTM模型"""model = Sequential()model.add(Bidirectional(LSTM(units=units, return_sequences=True), input_shape=input_shape))model.add(Dropout(dropout))model.add(Bidirectional(LSTM(units=units, return_sequences=False)))model.add(Dropout(dropout))model.add(Dense(units=25))model.add(Dense(units=1))model.compile(optimizer=Adam(learning_rate=0.001), loss='mean_squared_error')return modeldef train_model(self, model, X_train, y_train, X_val=None, y_val=None, epochs=100, batch_size=32, model_name=None):"""训练深度学习模型"""callbacks = [EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)]if model_name:callbacks.append(ModelCheckpoint(f'{model_name}.h5', save_best_only=True))# 如果没有提供验证集,使用训练集的20%作为验证集if X_val is None or y_val is None:validation_split = 0.2validation_data = Noneelse:validation_split = 0.0validation_data = (X_val, y_val)history = model.fit(X_train, y_train,epochs=epochs,batch_size=batch_size,validation_split=validation_split,validation_data=validation_data,callbacks=callbacks,verbose=1)if model_name:self.models[model_name] = modelreturn model, historydef evaluate_model(self, model, X_test, y_test):"""评估深度学习模型性能"""# 预测y_pred = model.predict(X_test)# 如果数据经过了标准化,需要还原if 'y' in self.scalers:y_test = self.scalers['y'].inverse_transform(y_test)y_pred = self.scalers['y'].inverse_transform(y_pred)# 计算评估指标mse = np.mean(np.square(y_test - y_pred))rmse = np.sqrt(mse)mae = np.mean(np.abs(y_test - y_pred))# 计算R方ss_tot = np.sum(np.square(y_test - np.mean(y_test)))ss_res = np.sum(np.square(y_test - y_pred))r2 = 1 - (ss_res / ss_tot)return {'MSE': mse,'RMSE': rmse,'MAE': mae,'R2': r2}def predict_future(self, model, last_sequence, n_steps=30, scaler=None):"""预测未来n天的股票价格"""predictions = []current_sequence = last_sequence.copy()for _ in range(n_steps):# 预测下一个值current_pred = model.predict(current_sequence)[0][0]predictions.append(current_pred)# 更新序列用于下一次预测current_sequence = np.roll(current_sequence, -1, axis=1)current_sequence[0, -1, 0] = current_pred# 如果有缩放器,需要还原数据if scaler is not None:predictions = scaler.inverse_transform(np.array(predictions).reshape(-1, 1))return predictionsdef save_model(self, model_name, file_path):"""保存模型"""if model_name in self.models:self.models[model_name].save(file_path)print(f"模型已保存至{file_path}")else:print(f"模型{model_name}不存在")def load_model(self, model_name, file_path):"""加载模型"""try:model = load_model(file_path)self.models[model_name] = modelprint(f"模型已从{file_path}加载")return modelexcept Exception as e:print(f"加载模型时出错: {e}")return Nonedef plot_training_history(self, history, title="模型训练历史"):"""绘制训练过程中的损失曲线"""plt.figure(figsize=(12, 6))plt.plot(history.history['loss'], label='训练集损失')plt.plot(history.history['val_loss'], label='验证集损失')plt.title(title)plt.xlabel('迭代次数')plt.ylabel('损失')plt.legend()plt.grid(True)plt.show()
5.4 集成模型
通过集成多个模型的预测结果,可以进一步提高预测的准确性:
import numpy as np
from sklearn.ensemble import VotingRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_scoreclass EnsembleModel:def __init__(self):self.models = {}self.ensemble_model = Nonedef add_model(self, name, model):"""添加模型到集成中"""self.models[name] = modelreturn selfdef create_voting_ensemble(self, weights=None):"""创建投票集成模型"""if not self.models:print("没有模型可以集成")return Noneestimators = [(name, model) for name, model in self.models.items()]self.ensemble_model = VotingRegressor(estimators=estimators, weights=weights)return self.ensemble_modeldef train_ensemble(self, X_train, y_train):"""训练集成模型"""if self.ensemble_model is None:print("请先创建集成模型")return Noneself.ensemble_model.fit(X_train, y_train)return self.ensemble_modeldef weighted_average_prediction(self, X, weights=None):"""使用加权平均方式集成预测结果"""if not self.models:print("没有模型可以集成")return Nonepredictions = []for name, model in self.models.items():pred = model.predict(X)predictions.append(pred)# 将预测结果转换为数组predictions = np.array(predictions)# 如果没有提供权重,使用平均值if weights is None:weights = np.ones(len(self.models)) / len(self.models)else:# 强制权重和为1weights = np.array(weights) / np.sum(weights)# 计算加权平均预测weighted_pred = np.sum(predictions * weights.reshape(-1, 1), axis=0)return weighted_preddef evaluate_ensemble(self, X_test, y_test):"""评估集成模型性能"""if self.ensemble_model is None:print("请先创建集成模型")return Noney_pred = self.ensemble_model.predict(X_test)mse = mean_squared_error(y_test, y_pred)rmse = np.sqrt(mse)mae = mean_absolute_error(y_test, y_pred)r2 = r2_score(y_test, y_pred)return {'MSE': mse,'RMSE': rmse,'MAE': mae,'R2': r2}def evaluate_weighted_ensemble(self, X_test, y_test, weights=None):"""评估加权集成模型性能"""y_pred = self.weighted_average_prediction(X_test, weights)mse = mean_squared_error(y_test, y_pred)rmse = np.sqrt(mse)mae = mean_absolute_error(y_test, y_pred)r2 = r2_score(y_test, y_pred)return {'MSE': mse,'RMSE': rmse,'MAE': mae,'R2': r2}
6. 数据可视化
数据可视化是股票预测分析系统的重要组成部分,可以直观地展示原始数据、技术指标和预测结果。
6.1 原始数据可视化
使用Matplotlib和Plotly等库可视化股票原始数据:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import numpy as np
from datetime import datetime, timedeltaclass StockDataVisualizer:def __init__(self, data=None):self.data = datadef load_data(self, data):"""加载数据"""self.data = datareturn selfdef plot_stock_price(self, title="股票价格趋势", figsize=(12, 6)):"""使用Matplotlib绘制股票价格趋势图"""if self.data is None or 'Close' not in self.data.columns:print("数据不包含收盘价")return Noneplt.figure(figsize=figsize)plt.plot(self.data.index, self.data['Close'], label='收盘价')# 设置日期格式plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))plt.gca().xaxis.set_major_locator(mdates.MonthLocator())plt.title(title)plt.xlabel('日期')plt.ylabel('价格')plt.legend()plt.grid(True)plt.xticks(rotation=45)plt.tight_layout()return pltdef plot_ohlc(self, title="股票OHLC图", figsize=(12, 6)):"""使用Matplotlib绘制OHLC图"""if self.data is None or not all(col in self.data.columns for col in ['Open', 'High', 'Low', 'Close']):print("数据不包含必要的价格列")return None# 创建图形fig, ax = plt.subplots(figsize=figsize)# 计算柱形图的宽度width = 0.6# 绘制价格柱形图up = self.data[self.data['Close'] >= self.data['Open']]down = self.data[self.data['Close'] < self.data['Open']]# 绘制上涨柱形图(绿色)ax.bar(up.index, up['Close'] - up['Open'], width, bottom=up['Open'], color='g')ax.bar(up.index, up['High'] - up['Close'], width/5, bottom=up['Close'], color='g')ax.bar(up.index, up['Open'] - up['Low'], width/5, bottom=up['Low'], color='g')# 绘制下跌柱形图(红色)ax.bar(down.index, down['Open'] - down['Close'], width, bottom=down['Close'], color='r')ax.bar(down.index, down['High'] - down['Open'], width/5, bottom=down['Open'], color='r')ax.bar(down.index, down['Close'] - down['Low'], width/5, bottom=down['Low'], color='r')# 设置日期格式ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))ax.xaxis.set_major_locator(mdates.MonthLocator())plt.title(title)plt.xlabel('日期')plt.ylabel('价格')plt.grid(True)plt.xticks(rotation=45)plt.tight_layout()return pltdef plot_candlestick_plotly(self, title="股票K线图"):"""使用Plotly绘制交互式K线图"""if self.data is None or not all(col in self.data.columns for col in ['Open', 'High', 'Low', 'Close']):print("数据不包含必要的价格列")return None# 创建K线图fig = go.Figure(data=[go.Candlestick(x=self.data.index,open=self.data['Open'],high=self.data['High'],low=self.data['Low'],close=self.data['Close'],name='K线')])# 添加5日和20日移动平均线if len(self.data) >= 20:fig.add_trace(go.Scatter(x=self.data.index,y=self.data['Close'].rolling(window=5).mean(),line=dict(color='blue', width=1),name='5日移动平均线'))fig.add_trace(go.Scatter(x=self.data.index,y=self.data['Close'].rolling(window=20).mean(),line=dict(color='orange', width=1),name='20日移动平均线'))# 更新布局fig.update_layout(title=title,xaxis_title='日期',yaxis_title='价格',xaxis_rangeslider_visible=False,template='plotly_white')return figdef plot_volume(self, title="成交量分析", figsize=(12, 6)):"""绘制成交量图"""if self.data is None or 'Volume' not in self.data.columns:print("数据不包含成交量")return Noneplt.figure(figsize=figsize)# 根据价格变化给成交量柱形图着色if 'Close' in self.data.columns:colors = ['g' if close_price > open_price else 'r' for close_price, open_price in zip(self.data['Close'], self.data['Close'].shift(1))]else:colors = 'b'plt.bar(self.data.index, self.data['Volume'], color=colors, alpha=0.8)# 添加移动平均线if len(self.data) >= 20:plt.plot(self.data.index, self.data['Volume'].rolling(window=20).mean(), color='orange', label='20日平均成交量')# 设置日期格式plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))plt.gca().xaxis.set_major_locator(mdates.MonthLocator())plt.title(title)plt.xlabel('日期')plt.ylabel('成交量')plt.legend()plt.grid(True)plt.xticks(rotation=45)plt.tight_layout()return pltdef plot_technical_indicators(self, indicators, title="技术指标分析", figsize=(12, 8)):"""绘制技术指标图"""if self.data is None:print("没有数据可绘制")return None# 检查指标是否存在for indicator in indicators:if indicator not in self.data.columns:print(f"指标{indicator}不存在")return None# 创建图形fig, ax = plt.subplots(figsize=figsize)# 绘制收盘价if 'Close' in self.data.columns:ax.plot(self.data.index, self.data['Close'], label='收盘价', color='black')# 绘制指标colors = ['blue', 'green', 'red', 'purple', 'orange', 'brown', 'pink', 'gray', 'olive', 'cyan']for i, indicator in enumerate(indicators):ax.plot(self.data.index, self.data[indicator], label=indicator, color=colors[i % len(colors)])# 设置日期格式ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))ax.xaxis.set_major_locator(mdates.MonthLocator())plt.title(title)plt.xlabel('日期')plt.ylabel('值')plt.legend()plt.grid(True)plt.xticks(rotation=45)plt.tight_layout()return plt
6.2 预测结果可视化
将模型预测结果进行可视化,直观展示预测效果:
class PredictionVisualizer:def __init__(self, actual_data=None, predicted_data=None):self.actual_data = actual_dataself.predicted_data = predicted_datadef load_data(self, actual_data, predicted_data):"""加载实际数据和预测数据"""self.actual_data = actual_dataself.predicted_data = predicted_datareturn selfdef plot_predictions(self, title="股票价格预测结果", figsize=(12, 6)):"""绘制预测结果与实际值对比图"""if self.actual_data is None or self.predicted_data is None:print("数据不完整")return Noneplt.figure(figsize=figsize)# 绘制实际值plt.plot(self.actual_data.index, self.actual_data, label='实际值', color='blue')# 绘制预测值if isinstance(self.predicted_data, pd.Series) and self.predicted_data.index.equals(self.actual_data.index):plt.plot(self.predicted_data.index, self.predicted_data, label='预测值', color='red', linestyle='--')else:plt.plot(self.actual_data.index, self.predicted_data, label='预测值', color='red', linestyle='--')# 设置日期格式plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))plt.gca().xaxis.set_major_locator(mdates.MonthLocator())plt.title(title)plt.xlabel('日期')plt.ylabel('价格')plt.legend()plt.grid(True)plt.xticks(rotation=45)plt.tight_layout()return pltdef plot_future_predictions(self, historical_data, future_predictions, prediction_dates=None, title="未来股票价格预测", figsize=(12, 6)):"""绘制历史数据和未来预测结果"""if historical_data is None or future_predictions is None:print("数据不完整")return Noneplt.figure(figsize=figsize)# 绘制历史数据plt.plot(historical_data.index, historical_data, label='历史数据', color='blue')# 生成预测日期(如果没有提供)if prediction_dates is None:last_date = historical_data.index[-1]if isinstance(last_date, pd.Timestamp):prediction_dates = [last_date + timedelta(days=i+1) for i in range(len(future_predictions))]else:prediction_dates = range(len(historical_data), len(historical_data) + len(future_predictions))# 绘制预测数据plt.plot(prediction_dates, future_predictions, label='未来预测', color='red', linestyle='--')# 添加分隔线plt.axvline(x=historical_data.index[-1], color='green', linestyle='-', label='当前日期')# 设置日期格式(如果是日期类型)if isinstance(historical_data.index[0], pd.Timestamp):plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))plt.gca().xaxis.set_major_locator(mdates.MonthLocator())plt.title(title)plt.xlabel('日期')plt.ylabel('价格')plt.legend()plt.grid(True)plt.xticks(rotation=45)plt.tight_layout()return pltdef plot_model_comparison(self, actual_data, predictions_dict, title="模型预测效果对比", figsize=(12, 6)):"""绘制多个模型的预测结果对比图"""if actual_data is None or not predictions_dict:print("数据不完整")return Noneplt.figure(figsize=figsize)# 绘制实际值plt.plot(actual_data.index, actual_data, label='实际值', color='black', linewidth=2)# 绘制各模型预测值colors = ['red', 'blue', 'green', 'purple', 'orange', 'brown', 'pink', 'gray']for i, (model_name, predictions) in enumerate(predictions_dict.items()):plt.plot(actual_data.index, predictions, label=f'{model_name}预测', color=colors[i % len(colors)], linestyle='--')# 设置日期格式plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))plt.gca().xaxis.set_major_locator(mdates.MonthLocator())plt.title(title)plt.xlabel('日期')plt.ylabel('价格')plt.legend()plt.grid(True)plt.xticks(rotation=45)plt.tight_layout()return pltdef plot_error_distribution(self, actual_data, predicted_data, title="预测误差分布", figsize=(12, 6)):"""绘制预测误差分布图"""if actual_data is None or predicted_data is None:print("数据不完整")return None# 计算误差errors = actual_data - predicted_dataplt.figure(figsize=figsize)# 绘制误差直方图plt.hist(errors, bins=30, alpha=0.7, color='blue')plt.title(title)plt.xlabel('预测误差')plt.ylabel('频次')plt.grid(True)plt.tight_layout()return plt
相关文章:
Python项目--基于机器学习的股票预测分析系统
1. 项目介绍 在当今数字化时代,金融市场的数据分析和预测已经成为投资决策的重要依据。本文将详细介绍一个基于Python的股票预测分析系统,该系统利用机器学习算法对历史股票数据进行分析,并预测未来股票价格走势,为投资者提供决策…...
第三阶段面试题
Nginx nginx常用模块以及其功能 proxy模块,进行代理功能 ssl模块,进行HTTPS协议的使用 gzip模块,进行传输数据的压缩 upstream模块,进行反向代理时使用 static模块,静态资源进行访问的模块 cache模块࿰…...
spring响应式编程系列:总体流程
目录 示例 程序流程 just subscribe new LambdaMonoSubscriber MonoJust.subscribe new Operators.ScalarSubscription onSubscribe request onNext 时序图 类图 数据发布者 MonoJust …...
基于PySide6与pyCATIA的圆柱体特征生成工具开发实战——NX建模之圆柱命令的参考与移植
引言 在机械设计领域,特征建模的自动化是提升设计效率的关键。本文基于PySide6与pycatia技术栈,深度解析圆柱特征自动化生成系统的开发实践,涵盖参数化建模、交互式元素选择、异常处理等核心模块,实现比传统手动操作提升3倍效率的…...
kafka jdbc connector适配kadb数据实时同步
测试结论 源端增量获取方式包括:bulk、incrementing、timestamp、incrementingtimestamp(混合),各种方式说明如下: bulk: 一次同步整个表的数据 incrementing: 使用严格的自增列标识增量数据。不支持对旧数据的更新…...
pgsql中使用jsonb的mybatis-plus和jps的配置
在pgsql中使用jsonb类型的数据时,实体对象要对其进行一些相关的配置,而mybatis和jpa中使用各不相同。 在项目中经常会结合 MyBatis-Plus 和 JPA 进行开发,MyBatis_plus对于操作数据更灵活,jpa可以自动建表,两者各取其…...
4.17-4.18学习总结 多线程
并发与并行: 并发和并行是有可能都在发生的。 多线程的实现方式: 第一种:创建子类对象,调用start方法启动线程。 第二种: 第三种: 第一种和第二种不可以获取到多线程结果,但第三章种可以。 多…...
无人机在农业中的应用与挑战!
一、无人机在农业中的作用 1. 提升作业效率与降低成本 无人机在喷洒农药、播种、施肥、吊运等环节显著提升效率。例如,湖北秭归县使用大疆T100无人机吊运脐橙,单次85公斤的运输任务仅需2分钟,而人工需1小时,综合成本降低250元…...
无刷电机槽数相同、转子极数不同的核心区别
一、基础原理差异 无刷电机的核心参数: 槽数(定子槽数,记为 ( Z )):定子铁芯上的绕组槽数量,决定绕组布局。极数(转子磁极数,记为 ( 2p )):转子上的永磁体磁极对数(总极数为 ( 2p ),如 ( p=4 ) 表示 8 极)。核心关系:槽极配合(( Z/2p ))决定电机电磁结构,相同…...
为您的照片提供本地 AI 视觉:使用 Llama Vision 和 ChromaDB 构建 AI 图像标记器
有没有花 20 分钟浏览您的文件夹以找到心中的特定图像或屏幕截图?您并不孤单。 作为工作中的产品经理,我总是淹没在竞争对手产品的屏幕截图、UI 灵感以及白板会议或草图的照片的海洋中。在我的个人生活中,我总是捕捉我在生活中遇到的事物&am…...
OpenAI 34页最佳构建Agent实践
penAI发布O4,也发布34页最佳构建Agent实践,值得阅读。 什么是Agent? 传统软件使用户能够简化和自动化工作流程,而代理能够以高度独立的方式代表用户执行相同的工作流程。 代理是能够独立地代表您完成任务的系统。 工作流程是必…...
第 5 期(进阶版):训练第一个 DDPM 模型(使用 CIFAR-10 数据集)
—— 用 DDPM 模型生成彩色图像,感受扩散魔法在 CIFAR-10 上的威力! 本期目标 将 MNIST 替换为 CIFAR-10; 模型结构适配 RGB 三通道输入; 保持原始扩散与采样流程; 增加图像可视化对比! 数据准备&…...
进程间通信(IPC)----共享内存
进程间通信(IPC)的共享内存机制允许不同进程直接访问同一块物理内存区域,是速度最快的IPC方式(无需数据拷贝)。 一、共享内存核心概念 1. 基本原理 共享内存区域:由内核管理的特殊内存段,可被…...
Xcode16 调整 Provisioning Profiles 目录导致证书查不到
cronet demo 使用的 ninja 打包,查找 Provisioning Profiles 路径是 ~/Library/MobileDevice/Provisioning Profiles,但 Xcode16 把该路径改为了 ~/Library/Developer/Xcode/UserData/Provisioning Profiles,导致在编译 cronet 的demo 时找不…...
Debian服务器环境下env变量丢失怎么办
在 Debian服务器环境下,如果出现了 env 环境变量丢失的问题,比如常见的 PATH、JAVA_HOME、PYTHONPATH 等系统变量或自定义变量不起作用,可能会导致一些命令无法执行、服务无法启动、脚本报错等。 这个问题常见于: 使用 cron、sy…...
搜广推校招面经七十八
字节推荐算法 一、实习项目:多任务模型中的每个任务都是做什么?怎么确定每个loss的权重 这个根据实际情况来吧。如果实习时候用了moe,就可能被问到。 loss权重的话,直接根据任务的重要性吧。。。 二、特征重要性怎么判断的&…...
ctf.show—Web(1-10)详细通关教程
Web1-签到题 1、按F12查看元素,发现有一段被注释的字符串 2、看起来并不像flag,格式类似于Base64编码 扔到Base64在线编码平台:Base64 编码/解码 - 锤子在线工具此工具是一个 Base64 编码或解码在线工具,实现把字符串转成 Base6…...
双层Key缓存
双层 Key 缓存是一种针对 缓存击穿 和 雪崩问题 的优化方案,其核心思想是通过 主备双缓存 的机制,确保在热点数据过期时仍能提供可用服务,同时降低对数据库的瞬时压力。以下是其核心原理、实现细节及适用场景的深度解析: 一、核心…...
android编译使用共享缓存
注意 服务器端与客户端系统的版本号需为Ubuntu20.04ccache版本不能低于4.4执行用户需要为sudo权限服务器端nfs目录权限必须为nobody:nogroup 一、服务端配置: 在服务器192.168.60.142上配置 NFS 共享 1.安装 NFS 服务器: 1 sudo apt-get install nfs…...
如何使用Labelimg查看已经标注好的YOLO数据集标注情况
文章目录 1、 安装并运行Labelimg1.1、安装Labelimg1.2、运行Labelimg 2、查看数据集标注情况2.1、创建类别名称文件classes.txt2.2、使用Labelimg打开查看标注文件2.3、正式标注 3、目标检测系列文章 本文主要介绍一下如何使用LabelImg查看已经标注好的YOLO数据集标注情况&…...
Web3架构下的数据隐私与保护
在这个信息爆炸的时代,Web3的概念如同一股清流,以其去中心化的特性,为数据隐私与保护带来了新的希望。Web3,也被称作下一代互联网,它通过区块链技术实现数据的去中心化存储和处理,旨在提高数据的安全性和隐…...
PCM 参数深度解析:采样率、帧、缓存大小与多通道关系
将下面的 PCM 配置作为例子: config.channels 2; // 立体声(2 个通道) config.rate 48000; // 采样率 48000 Hz,即每秒 48000 帧 config.period_size 1024; // 每个周…...
Kafka消费者端重平衡流程
重平衡的完整流程需要消费者 端和协调者组件共同参与才能完成。我们先从消费者的视角来审视一下重平衡的流程。在消费者端,重平衡分为两个步骤:分别是加入组和等待领导者消费者(Leader Consumer)分配方案。这两个步骤分别对应两类…...
【字节跳动AI论文】海姆达尔:生成验证的测试时间扩展
摘要:人工智能系统只能在能够验证知识本身的范围内创建和维护知识。 最近关于长链推理的研究表明,LLM在解决竞争问题方面具有巨大的潜力,但它们的验证能力仍然很弱,而且没有得到充分的研究。 在本文中,我们提出了Heimd…...
【Datawhale Al春训营】气象预测(AI+航空安全)竞赛笔记
这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…...
大模型应用开发实战:AI Agent与智能体开发技术解析
更多AI大模型应用开发学习内容,尽在聚客AI学院 一、AI Agent的核心概念 AI Agent(智能体)是基于大模型构建的自主任务执行系统,能够根据用户指令拆解目标、调用工具、完成复杂任务(如数据分析、自动化办公)…...
《Learning Langchain》阅读笔记3-基于 Gemini 的 Langchain如何从LLMs中获取特定格式
纯文本输出是有用的,但在某些情况下,我们需要 LLM 生成结构化输出,即以机器可读格式(如 JSON、XML 或 CSV)或甚至以编程语言(如 Python 或 JavaScript)生成的输出。当我们打算将该输出传递给其他…...
Mac mini 安装mysql数据库以及出现的一些问题的解决方案
首先先去官网安装一下mysql数据库,基本上都是傻瓜式安装的流程,我也就不详细说了。 接下来就是最新版的mysql安装的时候,他就会直接让你设置一个新的密码。 打开设置,拉到最下面就会看到一个mysql的图标: 我设置的就是…...
智能体时代的产业范式确立,中国企业以探索者姿态走出自己的路
作者 | 曾响铃 文 | 响铃说 当前,一个新的20年的产业升级期已经开启,系统性的发展路径也正在形成。 前不久,以“共建智能体时代“为主题的超聚变探索者大会2025在河南郑州举办。超聚变变数字技术有限公司(以下简称:…...
电路安全智控系统与主机安全防护系统主要功能是什么
电路安全智控系统被称为电路安全用电控制系统。电路安全智控系统具备一系列强大且实用的功能。电路安全智控系统能够对总电压、总电流、总功率、总电能,以及各分路的电压、电流、功率、电能和功率因素等进行全方位的监控。在大型工厂的电力分配中,通过对…...
MCP Server驱动传统SaaS智能化转型:从工具堆叠到AI Agent生态重构,基于2025年技术演进与产业实践
MCP Server驱动传统SaaS智能化转型:从工具堆叠到AI Agent生态重构 (基于2025年技术演进与产业实践) MCP模型上下文协议 一、技术底座革新:MCP协议重构AI时代的"数字接口" 传统SaaS软件向大模型AI应用转型的核心矛盾…...
【工具变量】地市农业播种面积及粮食产量等21个相关指标(2013-2022年)
粮食产量、粮食播种面积及农作物播种面积等,是衡量农业发展水平和粮食安全的重要指标。随着全球粮食需求的持续增长,准确掌握这些数据对制定农业政策、优化生产结构和提高农业生产效率至关重要。因此,缤本次分享数据包括《中国统计NJ》、《中…...
使用 PySpark 批量清理 Hive 表历史分区
使用 PySpark 批量清理 Hive 表历史分区 在大数据平台中,Hive 表通常采用分区方式存储数据,以提升查询效率和数据管理的灵活性。随着数据的不断积累,历史分区会越来越多,既占用存储空间,也影响元数据管理性能。因此&a…...
A. k-th equality(1700)
Problem - 1835A - Codeforces Daily_CF_Problems/daily_problems/2025/04/0417/solution/cf1835a.md at main Yawn-Sean/Daily_CF_Problems 考虑所有形式为 abc 的等式,其中 a有 A 位数, b 有 B 位数, c 有 C 位数。所有数字都是正整数,求…...
深度学习-torch,全连接神经网路
3. 数据集加载案例 通过一些数据集的加载案例,真正了解数据类及数据加载器。 3.1 加载csv数据集 代码参考如下 import torch from torch.utils.data import Dataset, DataLoader import pandas as pd class MyCsvDataset(Dataset):def __init__(self, fil…...
echarts饼图中心呈现一张图片,并且能动态旋转的效果react组件
实现效果: 父组件: import React from react import styles from ./style.less import GaugeChart from ./GaugeChart;export default function index() {return (<div><div className{styles.bg} ></div><div style{{ width: 500…...
使用Docker搭建开源Email服务器
使用Docker搭建开源Email服务器 1 介绍 开源的Email服务器比较多,例如:poste.io、MailCatcher、Postal、mailcow等。由于poste.io支持docker安装,页面比较美观,使用简单,支持SMTP IMAP POP3等协议,安全…...
css图片设为灰色
使用filter方式将图片设置为灰色 普通图片使用:filter: saturate(0); 纯白图片使用: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"width…...
2025 年第十五届 MathorCup竞赛赛题浅析-助攻快速选题
本届妈杯竞赛各赛题难度均已经达到了国赛难度,也更好的回应了大家更为关心的,在当前AI环境下,似乎“数学建模变成了AI使用竞赛一样”。但是国委会一直以来都是一个态度:AI现在是无法直接解决任何一个国赛赛题的。对应的如今这句话…...
【android bluetooth 案例分析 03】【PTS 测试 1】【pts基本介绍】
Bluetooth SIG(Special Interest Group)提供的 PTS(Profile Tuning Suite)测试 是蓝牙认证过程中一项极为关键的步骤。它主要用于验证设备是否符合 Bluetooth SIG 制定的各项 蓝牙规范(Bluetooth Specification&#x…...
Java集合框架深度解析:HashMap、HashSet、TreeMap、TreeSet与哈希表原理详解
一、核心数据结构总览 1. 核心类继承体系 graph TDMap接口 --> HashMapMap接口 --> TreeMapSet接口 --> HashSetSet接口 --> TreeSetHashMap --> LinkedHashMapHashSet --> LinkedHashSetTreeMap --> NavigableMapTreeSet --> NavigableSet 2. 核心…...
【深度学习】张量计算:爱因斯坦求和约定|tensor系列03
博主简介:努力学习的22级计算机科学与技术本科生一枚🌸博主主页: Yaoyao2024往期回顾:【深度学习】详解矩阵乘法、点积,内积,外积、哈达玛积极其应用|tensor系列02每日一言🌼: “岱宗夫如何&…...
OpenHarmony-Risc-V上运行openBLAS中的benchmark
OpenHarmony-Risc-V上运行openBLAS中的benchmark 文章目录 OpenHarmony-Risc-V上运行openBLAS中的benchmark前言一、编译openBLAS1.源码下载2.工具链下载3.编译并安装openBLAS 二、编译open BLAS中的benchmark三、上设备运行总结 前言 参考https://zhuanlan.zhihu.com/p/18825…...
CCF CSP 第36次(2024.12)(2_梦境巡查_C++)
CCF CSP 第36次(2024.12)(2_梦境巡查_C) 解题思路:思路一: 代码实现代码实现(思路一): 时间限制: 1.0 秒 空间限制: 512 MiB 原题链接 解题思路…...
windows下安装mcp servers
以sequential-thinking为例 macos下安装就像github readme中那样安装即可: {"mcpServers": {"sequential-thinking": {"command": "npx","args": ["-y","modelcontextprotocol/server-sequenti…...
OpenGauss 数据库介绍
OpenGauss 数据库介绍 OpenGauss 是华为基于 PostgreSQL 开发的企业级开源关系型数据库,现已成为开放原子开源基金会的项目。以下是 OpenGauss 的详细介绍: 一 核心特性 1.1 架构设计亮点 特性说明优势多核并行NUMA感知架构充分利用现代CPU多核性能行…...
Web3区块链网络中数据隐私安全性探讨
在这个信息爆炸的时代,Web3 的概念如同一股清流,以其去中心化、透明性和安全性的特点,为数据隐私保护提供了新的解决方案。本文将探讨 Web3 区块链网络中数据隐私的安全性问题,并探索如何通过技术手段提高数据隐私的保护。 Web3 …...
linux驱动之poll
驱动中 poll 实现 在用户空间实现事件操作的一个主要实现是调用 select/poll/epoll 函数。那么在驱动中怎么来实现 poll 的底层呢? 其实在内核的 struct file_operations 结构体中有一个 poll 成员,其就是底层实现的接口函数。 驱动中 poll 函数实现原…...
【最后203篇系列】028 FastAPI的后台任务处理
说明 今天偶然在别的文章里看到这个功能,突然觉得正好。 CeleryWorker已经搭好了,但是我一直想在用户请求时进行额外的处理会比较影响处理时间,用这个正好可以搭配上。 我设想的一个场景: 1 用户发起请求2 接口中进行关键信息…...
微信小程序中,将搜索组件获取的值传递给父页面(如 index 页面)可以通过 自定义事件 或 页面引用 实现
将搜索组件获取的值传递给父页面(如 index 页面)可以通过 自定义事件 或 页面引用 实现 方法 1:自定义事件(推荐) 步骤 1:搜索组件内触发事件 在搜索组件的 JS 中,当获取到搜索值时,…...