LSTM神经网络 vs Transformer在量化中的应用

LSTM,全称Long Short-Term Memory,是一种特殊的递归神经网络。它通过巧妙的"门"结构,可以有效地捕捉时间序列数据中的长期依赖关系。这一特点,使得LSTM在处理股价这种具有时间序列特性的数据时,展现出了非凡的潜力。

这种特殊的递归神经网络 与一般的前馈神经网络不同,当使用前馈神经网络时,神经网络会认为我们 𝑡 时刻输入的内容与 𝑡+1 时刻输入的内容完全无关,对于许多情况,例如图片分类识别,这是毫无问题的,可是对于一些情景,例如自然语言处理 (NLP, Natural Language Processing) 或者我们需要分析类似于连拍照片这样的数据时,合理运用 𝑡 或之前的输入来处理 𝑡+𝑛 时刻显然可以更加合理的运用输入的信息。为了运用到时间维度上信息,人们设计了递归神经网络 (RNN, Recurssion Neural Network),一个简单的递归神经网络可表示为:

图中, 𝑥𝑡 是在 𝑡 时刻的输入信息, ℎ𝑡 是在 𝑡 时刻的输出信息,可以看到神经元 𝐴 会递归的调用自身并且将 𝑡−1 时刻的信息传递给 𝑡 时刻。递归神经网络在许多情况下运行良好,特别是在对短时间序列数据的分析时十分方便。但上图所示的简单递归神经网络存在一个“硬伤“,长期依赖问题:递归神经网络只能处理上下文较接近的情况:

Exp 1. 想象现在设计了一个基于简单RNN的句子自动补全器,当我输入"Sea is ..." 的时候会自动补全为"Sea is  blue"。

在这种情况下,我们需要获取从上文获取的信息极短,而RNN可以很好的收集到 𝑡=0 时的信息"Sea"并且补上"blue"

Exp 2. 现在,假设我们用刚刚的RNN试图补全一篇文章"我一直呆在中国,……,我会说一口流利的 (?)"。

在这里,为了补全最后的空缺,需要的信息可能在非常远的上文提到的”中国“。在实验中简单的理想状态下,经过精心调节的RNN超参数可以良好的将这些信息向后传递。可是在现实的情况中,基本没有RNN可以做到这一点。不但如此,相比于一般的神经网络,这种简单的RNN还很容易出现两种在神经网络中臭名昭著的问题:梯度消失问题(神经网络的权重/偏置梯度极小,导致神经网络参数调整速率急剧下降:0.99^{365})和梯度爆炸问题(神经网络的权重/偏置梯度极大,导致神经网络参数调整幅度过大,矫枉过正:1.01^{365})。对于任意信息递归使用足够多次同样的计算,都会导致极大或极小的结果。

根据微分链式法则,在RNN中,神经元的权重的梯度可以被表示为一系列函数的微分的连乘。因为神经元的参数(权重与偏置)都是基于学习速率(一般为常数)和参数梯度相反数(使得神经网络输出最快逼近目标输出)得到的,一个过小或过大的梯度会导致我们要么需要极长的训练时间(本来从-2.24 调节到 -1.99 只用500个样本,由于梯度过小,每次只调10^{-6} ,最后用了几万个样本),要么会导致参数调节过度(例如本来应该从-10.02调节到-9.97,由于梯度过大,直接调成了20.7)。

基于以上问题,LSTM的设计者提出了“长短期记忆”的概念——只有一部分的信息需要长期的记忆,而有的信息可以不记下来。同时,还需要一套机制可以动态的处理神经网络的“记忆”,因为有的信息可能一开始价值很高,后面价值逐渐衰减,这时候我们也需要让神经网络学会“遗忘”特定的信息,这就是下面提到的遗忘门、记忆门、输出门。

一个普通的,使用tanh作为激活函数的RNN可以这么表示:

这里A在 𝑡−1 时刻的输出值h_{t-1}被复制到了 𝑡 时刻,与 𝑡 时刻的输入x_{t}整合后经过一个带权重和偏置的tanh函数后形成输出,并继续将数据复制到 𝑡+1 时刻。

与上图朴素的RNN相比,单个LSTM单元拥有更加复杂的内部结构和输入输出:

上图中每一个红色圆形代表对向量做出的操作(pointwise operation, 对位操作),而黄色的矩形代表一个神经网络层,上面的字符代表神经网络所使用的激活函数

point-wise operation 对位操作
如果我要对向量<1, 2, 3> 和 <1, 3, 5>进行逐分量的相乘操作,会获得结果 <1, 6, 15>
layer 函数层
一个函数层拥有两个属性:权重向量(Weight) 和 偏置向量(bias),对于输入向量 𝐴 的每一个分量 𝑖 , 函数层会对其进行以下操作(假设激活函数为 𝐹(𝑥) ): output_{i}=F(W_{i}*A_{i}+b_{i})常见的激活函数(也就是套在最外面的 𝐹(𝑥) )有ReLU(线性修正单元),sigmoid(写作 𝜎 ),和 tanh

LSTM的关键:单元状态

LSTM能够从RNN中脱颖而出的关键就在于图中从单元中贯穿而过的线 ——神经元的隐藏态(单元状态),可将神经元的隐藏态简单的理解成递归神经网络对于输入数据的“记忆”,用C_{t}表示神经元在 𝑡 时刻过后的“记忆”,这个向量涵盖了在 𝑡+1 时刻前神经网络对于所有输入信息的“概括总结”

LSTM_1 遗忘门

对于上一时刻LSTM中的单元状态来说,一些“信息”可能会随着时间的流逝而“过时”。为了不让过多记忆影响神经网络对现在输入的处理,模型应该选择性遗忘一些在之前单元状态中的分量——这个工作就交给了“遗忘门”,每一次输入一个新的输入,LSTM会先根据新的输入和上一时刻的输出决定遗忘掉之前的哪些记忆——输入和上一步的输出会整合为一个单独的向量,然后通过sigmoid神经层,最后点对点的乘在单元状态上。因为sigmoid 函数会将任意输入压缩到 (0,1) 的区间上,因此可以非常直觉的得出这个门的工作原理 —— 如果整合后的向量某个分量在通过sigmoid层后变为0,那么显然单元状态在对位相乘后对应的分量也会变成0,换句话说,“遗忘”了这个分量上的信息;如果某个分量通过sigmoid层后为1,单元状态会“保持完整记忆”。不同的sigmoid输出会带来不同信息的记忆与遗忘。通过这种方式,LSTM可以长期记忆重要信息,并且记忆可以随着输入进行动态调整, 计算遗忘门的公式为,其中 𝑓𝑡 就是sigmoid神经层的输出向量:

画图表示为:

 

LSTM_2 & 3 记忆门

记忆门是用来控制是否将在 𝑡时刻(现在)的数据并入单元状态中的控制单位。首先,用tanh函数层将现在的向量中的有效信息提取出来,然后使用(图上tanh函数层左侧)sigmoid函数来控制这些记忆要放“多少”进入单元状态。这两者结合起来就可以做到:

  1. 从当前输入中提取有效信息
  2. 对提取的有效信息做出筛选,为每个分量做出评级(0 ~ 1),评级越高的最后会有越多的记忆进入单元状态

下面的公式分别表示这两个步骤在LSTM中的计算:

LSTM_4 输出门

输出门就是LSTM单元用于计算当前时刻的输出值的神经层。输出层会先将当前输入值与上一时刻输出值整合后的向量(也就是公式中的 [ℎ𝑡−1,𝑥𝑡] )用sigmoid函数提取其中的信息,接着会将当前的单元状态通过tanh函数压缩映射到区间(-1, 1)中。

为什么我们要在LSTM的输出门上使用tanh函数?
1. 为了防止 梯度消失问题,我们需要一个二次导数在大范围内不为0的函数,而tanh函数可以满足这一点
2. 为了便于凸优化,我们需要一个 单调函数
3. tanh函数一般收敛的更快
4. tanh函数的求导占用系统的资源更少

将经过tanh函数处理后的单元状态与sigmoid函数处理后的,整合后的向量点对点的乘起来就可以得到LSTM在 𝑡 时刻的输出了!

对于任何机器学习任务,数据都是一切的基石。而对于股价预测这样的时间序列问题,我们需要的是结构化的时间序列数据。为了方便直接用接口了:

import akshare as ak
# data = ak.stock_zh_a_minute(symbol='sz000001',period='1',adjust="") #  1, 5, 15, 30, 60
df = ak.stock_zh_a_hist(symbol="000001", period="daily", start_date="20100301", end_date='20240508', adjust="")

对数据进行一些预处理。这包括检查和填补缺失值,以及将数据归一化到0到1的范围内。归一化可以帮助神经网络更快地收敛。

pd.isna(df).sum()

import pandas as pd
from sklearn.preprocessing import MinMaxScaler
df = df[['日期', '开盘', '收盘', '最高', '最低', '成交量', '成交额']]
df.columns=['trade_date', 'open', 'close', 'high', 'low', 'vol','amount']df['trade_date'] = pd.to_datetime(df['trade_date'])
df.set_index('trade_date', inplace=True)# 填补缺失值(如果有的话)
# df.fillna(method="ffill", inplace=True)# 选择要预测的特征
features = ["open", "high", "low", "close", "vol"]# 归一化数据
scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(df[features])# 将归一化后的数据转换为DataFrame
scaled_df = pd.DataFrame(scaled_data, columns=features, index=df.index)

 用Keras库来搭建神经网络。首先需要将数据转换为LSTM所需的格式。LSTM期望数据具有以下形状:[样本数,时间步数,特征数]。时间步数表示我们要根据过去多少天的数据来预测未来的股价。

import numpy as np# 设定时间步数
time_steps = 60# 准备LSTM输入数据
X = []
y = []for i in range(time_steps, len(scaled_df)):X.append(scaled_df[i-time_steps:i])y.append(scaled_df["close"][i])X = np.array(X)
y = np.array(y)

这里设定时间步数为60,即根据过去60天的数据预测下一天的收盘价。然后,用一个循环来准备LSTM的输入数据。对于每个时间点,取前60天的数据作为输入,下一天的收盘价作为预测目标。接下来搭建LSTM模型:

from keras.models import Sequential
from keras.layers import LSTM, Dense, Dropout# 构建LSTM模型
model = Sequential()
model.add(LSTM(units=50, return_sequences=True, input_shape=(X.shape[1], X.shape[2])))
model.add(Dropout(0.2))
model.add(LSTM(units=50, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(units=50))
model.add(Dropout(0.2))
model.add(Dense(units=1))model.compile(optimizer="adam", loss="mean_squared_error")

KerasSequential模型来搭建LSTM网络。网络包含三层LSTM,每层有50个神经元。在每个LSTM层之后,我们添加了一个Dropout层来防止过拟合。最后添加一个全连接层来输出预测结果。用Adam优化器和均方误差损失函数MSE来编译模型。

开始训练模型,神经网络通过不断调整权重,从数据中学习模式和规律:

# 训练模型
model.fit(X, y, epochs=100, batch_size=32)

这里调用模型的fit方法来训练网络。设置训练的轮数(epochs)为100,每个批次(batch)的大小为32。这意味着,神经网络将遍历整个训练数据集100次,每次更新权重时使用32个样本。在训练过程中会看到每个epoch的损失值(loss)。损失值越低,通常意味着模型的性能越好。

模型评估:将数据分为训练集和测试集,用训练集数据训练模型,然后在测试集上评估模型的预测能力。

from sklearn.metrics import mean_squared_error# 进行预测
y_pred = model.predict(X)# 计算均方误差
mse = mean_squared_error(y, y_pred)
print(f"Mean Squared Error: {mse}")

简单画了一下走势图:

预测值和实际值偏离度不大。 

上面是用训练好的模型对输入数据进行预测,得到预测值y_pred。然后,我们使用mean_squared_error函数计算预测值和真实值之间的均方误差(MSE)。MSE是一个常用的回归问题的评估指标,它衡量了预测值与真实值之间的平均squared距离。MSE越小,通常意味着模型的预测性能越好。得到的结果为:

如果你对模型的性能满意,就可以用它来进行实际的股价预测了。为了进行预测,需要准备最近60天的股价数据作为输入(这里仅训练了一个特征,需要重新初始化一下):

# 准备最近60天的数据
last_60_days = scaled_df[-60:]
last_60_days_arr = np.array(last_60_days)
last_60_days_arr = np.reshape(last_60_days_arr, (1, last_60_days_arr.shape[0], last_60_days_arr.shape[1]))# 重新初始化scaler对象,只包含一个特征的归一化信息
scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(df['close'].values.reshape(-1, 1))# 进行预测
pred_price = model.predict(last_60_days_arr)# 将预测值反归一化
pred_price = scaler.inverse_transform(pred_price)print(f"Predicted Price: {pred_price[0][0]}")

下面输出了预测的股价。这个预测价格表示模型对下一个交易日收盘价的预期。当然,这只是一个预测,你如果相信就死定了(明天可能会回到10.8):

模型优化

虽然已经能够用LSTM模型来预测股价,但模型的性能还有很大的提升空间。以下是一些可能的优化策略:

  1. 增加特征:除了开盘价、最高价、最低价、收盘价和成交量,我们还可以加入其他技术指标,如移动平均线、RSI、MACD等。这些指标可能包含了一些有助于预测的信息。

  2. 调整模型结构:我们可以尝试不同的LSTM层数、神经元数、激活函数、正则化方法等,以找到最优的模型结构。这可能需要一些反复试验和调优。

  3. 引入注意力机制:注意力机制可以帮助模型更好地关注到重要的时间步。我们可以在LSTM层之上添加一个注意力层,让模型自动学习每个时间步的权重。

  4. 集成学习:我们可以训练多个不同的LSTM模型,然后将它们的预测结果进行平均或投票。这种集成学习的方法通常可以提高预测的稳健性和准确性。

  5. 引入更多数据:除了历史价格数据,我们还可以考虑引入一些基本面数据,如公司财报、宏观经济指标等。这可能需要我们对数据进行更复杂的预处理和特征工程。

如3引入self-attention机制的模型训练:

from keras.models import Model
from keras.layers import Input, LSTM, Dense, Dropout, Activation, Permute, multiply# 构建带注意力机制的LSTM模型
input_data = Input(shape=(time_steps, X.shape[2]))
lstm_out = LSTM(60, return_sequences=True)(input_data)
attention_probs = Dense(time_steps, activation='softmax', name='attention_probs')(lstm_out)
attention_mul = multiply([lstm_out, attention_probs])
attention_mul = Permute((2,1))(attention_mul)
final_output = Dense(1)(attention_mul)model = Model(input_data, final_output)
model.compile(optimizer='adam', loss='mean_squared_error')# 训练模型
model.fit(X, y, epochs=200, batch_size=32)

得到的结果为:

Transformer模型在NLP领域掀起了一场革命,其独特的自注意力机制和并行计算架构,让其在机器翻译、文本生成等任务上大幅刷新了SOTA记录。更重要的是,Transformer并不限于文本数据,其处理序列数据的能力同样可以拓展到时间序列领域。将Transformer应用于金融市场建模时,其记忆容量和建模能力可显著超越传统的RNN模型。直观来说,股票市场蕴藏着极为复杂的多尺度动力学过程,价格波动受基本面、资金面、市场情绪等诸多因素的交互影响,这些影响往往跨越不同的时间尺度。Transformer凭借其强大的注意力机制,能够自适应地关注不同时间尺度上的关键特征,挖掘出价格波动背后的深层逻辑,可谓深度长期记忆建模的利器。

Transformer的一些重要组成部分和特点:

自注意力机制(Self-Attention):这是Transformer的核心概念之一,它使模型能够同时考虑输入序列中的所有位置,而不是像循环神经网络(RNN)或卷积神经网络(CNN)一样逐步处理。自注意力机制允许模型根据输入序列中的不同部分来赋予不同的注意权重,从而更好地捕捉语义关系。
多头注意力(Multi-Head Attention):Transformer中的自注意力机制被扩展为多个注意力头,每个头可以学习不同的注意权重,以更好地捕捉不同类型的关系。多头注意力允许模型并行处理不同的信息子空间。
堆叠层(Stacked Layers):Transformer通常由多个相同的编码器和解码器层堆叠而成。这些堆叠的层有助于模型学习复杂的特征表示和语义。
位置编码(Positional Encoding):由于Transformer没有内置的序列位置信息,它需要额外的位置编码来表达输入序列中单词的位置顺序。
残差连接和层归一化(Residual Connections and Layer Normalization):这些技术有助于减轻训练过程中的梯度消失和爆炸问题,使模型更容易训练。
编码器和解码器:Transformer通常包括一个编码器用于处理输入序列和一个解码器用于生成输出序列,这使其适用于序列到序列的任务,如机器翻译。

Transformer的结构:
Nx = 6,Encoder block由6个encoder堆叠而成,图中的一个框代表的是一个encoder的内部结构,一个Encoder是由Multi-Head Attention和全连接神经网络Feed Forward Network构成。如下图所示:

每一个编码器都对应上图的一个encoder结构:

Transformer的编码组件是由6个编码器叠加在一起组成的,解码器同样如此。所有的编码器在结构上是相同的,但是它们之间并没有共享参数。从编码器输入的句子首先会经过一个自注意力层,这一层帮助编码器在对每个单词编码的时候时刻关注句子的其它单词。解码器中的解码注意力层的作用是关注输入句子的相关部分,类似于seq2seq的注意力。原结构中使用到的是多头注意力机制(Multi-Head Attention)。

Multi-Head Attention:

数据集准备:

搭建模型:

数据预处理与模型训练:

模型评估与预测:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/8518.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++语法|如何写出高效的C++代码(一)|对象使用过程中背后调用了哪些方法(构造和析构过程)?

文章目录 再探拷贝构造函数和重载复制运算符实例化新对象和赋值操作强转为类类型指针和引用时临时对象的构造和析构过程 考考你问题答案 再探拷贝构造函数和重载复制运算符 实例化新对象和赋值操作 首先我们写一个类&#xff0c;实现它的拷贝构造并重载赋值运算符。 class T…

盘点四种计算数组中元素值为1的个数的方法

目录 一、引言 二、方法一&#xff1a;基础循环遍历 三、方法二&#xff1a;列表推导式 四、方法三&#xff1a;使用内置函数sum和生成器表达式 五、方法四&#xff1a;使用NumPy库 六、性能比较 七、性能结果分析与讨论 八、最佳实践 九、总结 一、引言 在编程和数…

银河麒麟QT项目打包详细教程

银河麒麟QT项目打包详细教程 一、QT项目打包 下载linuxdeployqt&#xff0c;下载地址&#xff1a;https://github.com/probonopd/linuxdeployqt/releases 安装Linuxdeployqt 2.1 为了安装方便&#xff0c;将下载下来的文件名称改短些 mv linuxdeployqt-6-x86_64.AppImage lin…

92、动态规划-最小路径和

思路&#xff1a; 还是一样&#xff0c;先使用递归来接&#xff0c;无非是向右和向下&#xff0c;然后得到两种方式进行比较&#xff0c;代码如下&#xff1a; public int minPathSum(int[][] grid) {return calculate(grid, 0, 0);}private int calculate(int[][] grid, int …

射频无源器件之巴伦

一. 巴伦的作用 Balun,balanced-unbalanced的缩写,即平衡-不平衡转换器,是一种三端口无源器件,其本质是通过电感线圈的相互耦合实现的信号转换。用于平衡信号(差分信号,即振幅相等、相位相差180 的两个信号)与非平衡信号(单端信号)的相互转换。 Balun是高频电路重要器…

Vmware虚拟机瘦身及Samba服务不可用问题解决

虚拟机磁盘空间膨胀是一个令人头疼的问题&#xff0c;特别是对许多搞开发的小伙伴。无论是做后台服务、嵌入式还是Android开发&#xff0c;都面临着这个难题。首先&#xff0c;操作系统本身就已占用不少空间&#xff0c;更新安装包&#xff0c;再下载一些开源软件&#xff0c;剩…

运行Spring Boot项目失败?显示java: 无法访问org.springframework.boot.SpringApplication,让我来看看~

idea项目运行报错截图&#xff1a; &#xff08;1&#xff09;查看错误提示“类文件具有错误的版本 61.0, 应为 52.0”&#xff0c;61.0对应的是jdk17&#xff0c;52.0对应1.8。 通过这个网址可以查询版本&#xff1a; https://stackoverflow.com/questions/9170832/list-of-ja…

网络编程入门之UDP编程

欢迎各位帅哥美女来捧场&#xff0c;本文是介绍UDP网络编程。在这里&#xff0c;你会见到最详细的教程&#xff1b;细致到每一行代码&#xff0c;每一个api的由来和使用它的目的等。 目录 1.UDP相关API 1.1.两个类 1.2.两个类中的方法 2.UDP编程 2.1.大体框架 2.2.内容构…

【项目学习01_2024.05.08_Day06】

学习笔记 5 新增课程5.1 需求分析5.1.1 业务流程5.1.2 数据模型 5.2 接口定义5.3 接口开发5.3.1 保存课程基本信息5.3.2 保存营销信息 5.4 接口测试 5 新增课程 5.1 需求分析 5.1.1 业务流程 5.1.2 数据模型 5.2 接口定义 5.3 接口开发 根据需求分析&#xff0c;新增课程表…

【智能楼宇秘籍】一网关多协议无缝对接BACnet+OPC+MQTT

在繁华的都市中心&#xff0c;一座崭新的大型商业综合体拔地而起&#xff0c;集购物、餐饮、娱乐、办公于一体&#xff0c;是现代城市生活的缩影。然而&#xff0c;这座综合体的幕后英雄——一套高度集成的楼宇自动化系统&#xff0c;正是依靠多功能协议网关&#xff0c;实现了…

韩国站群服务器提供高级安全防护以确保数据和网站的安全性

韩国站群服务器提供高级安全防护以确保数据和网站的安全性 在当今数字化时代&#xff0c;网站的安全性和数据保护已成为企业和个人不可忽视的重要议题。韩国站群服务器作为一个拥有发达科技和互联网基础设施的国家&#xff0c;通过提供高级安全防护措施&#xff0c;为用户的数…

Web服务器和Tomcat

Web介绍 对于http协议操作进行封装、简化web程序开发 部署web项目&#xff0c;对外提供上网信息浏览 Tomcat介绍 一个轻量级的web服务器 也称为web容器 Tomcat的文件夹介绍 下载地址&#xff1a;Apache Tomcat - Apache Tomcat 9 Software Downloads 安装&#xff1a;直…

十个数据安全最佳实践:保护数据的简单方法

在德迅云安全将介绍数据安全的主要原则&#xff0c;并了解适用于大多数行业的 10 种数据安全最佳实践&#xff0c;以及云端安全检测的重要性。 数据威胁和维护数据安全的好处 什么是数据安全&#xff1f; 数据安全是旨在保护组织敏感资产的流程和工具的组合。有价值的数据在…

JavaScript快速入门系列-1(JavaScript简介)

第一章:JavaScript简介 1. JavaScript简介1.1 什么是JavaScript1.2 JavaScript的历史与应用1.3 环境搭建:浏览器与Node.js2. JavaScript语言基础2.1 变量声明:let, const, var2.2 数据类型:字符串、数字、布尔值、对象、数组、null与undefined2.3 运算符:算术、比较、逻辑…

二叉树的前序、中序、后序遍历的C++实现

二叉树的前序、中序、后序 遍历属于深度优先搜索方式&#xff0c;本文使用递归法实现前序、中序、后序的遍历方法&#xff0c;代码如下&#xff1a; #include <iostream> #include <vector>struct TreeNode{int val;TreeNode* left;TreeNode* right;TreeNode(int …

初识C++ · 模板初阶

目录 1 泛型编程 2 函数模板 3 类模板 1 泛型编程 模板是泛型编程的基础&#xff0c;泛型我们碰到过多次了&#xff0c;比如malloc函数返回的就是泛型指针&#xff0c;需要我们强转。 既然是泛型编程&#xff0c;也就是说我们可以通过一个样例来解决类似的问题&#xff0c…

Java基础之《mybatis-plus多数据源配置》

1、pom文件引入依赖 引入MyBatis-Plus之后请不要再次引入MyBatis以及mybatis-spring-boot-starter和MyBatis-Spring&#xff0c;以避免因版本差异导致的问题 <!--引入 MyBatis-Plus 之后请不要再次引入 MyBatis 以及 mybatis-spring-boot-starter和MyBatis-Spring&#xff0…

【C++】STL_ string的使用 + 模拟实现

前言 目录 1. STL简介&#xff08;1&#xff09;什么是STL&#xff08;2&#xff09;STL的版本&#xff08;3&#xff09;STL的六大组件 2. string的使用2.1 npos2.2 遍历字符串string的每一个字符2.3 迭代器&#xff1a;2.4 string的内存管理2.5 string模拟实现2.5.1 深拷贝&a…

Redis(主从复制搭建)

文章目录 1.主从复制示意图2.搭建一主多从1.搭建规划三台机器&#xff08;一主二从&#xff09;2.将两台从Redis服务都按照同样的方式配置&#xff08;可以理解为Redis初始化&#xff09;1.安装Redis1.yum安装gcc2.查看gcc版本3.将redis6.2.6上传到/opt目录下4.进入/opt目录下然…

iptables---防火墙

防火墙介绍 防火墙的作用可以理解为是一堵墙&#xff0c;是一个门&#xff0c;用于保护服务器安全的。 防火墙可以保护服务器的安全&#xff0c;还可以定义各种流量匹配的规则。 防火墙的作用 防火墙具有对服务器很好的保护作用&#xff0c;入侵者必须穿透防火墙的安全防护…