AI量化模型预测挑战赛 第二次学习笔记

news2024/9/25 5:23:26

        有关竞赛信息以及基础baseline代码解读请看我的上一篇文章

AI量化模型预测——baseline学习笔记_寂ღ᭄秋࿐的博客-CSDN博客

         在经过baseline进行详细的分析之后,接下来的方向肯定是奔着提分去的,下面我就从五个方面进行一一列出提分思路

  • 提取更多的特征
  • 特征筛选方案
  • 内存压缩
  • 验证方式
  • 模型集成

一、提取更多的特征

1. 完善baseline特征

(1)增加构建买二卖二、买三卖三、买四卖四相关特征

# 计算加权平均价格(wap)以及相关特征
train_df['wap2'] = (train_df['n_bid2'] * train_df['n_bsize2'] + train_df['n_ask2'] * train_df['n_asize2']) / (train_df['n_bsize2'] + train_df['n_asize2'])
train_df['wap3'] = (train_df['n_bid3'] * train_df['n_bsize3'] + train_df['n_ask3'] * train_df['n_asize3']) / (train_df['n_bsize3'] + train_df['n_asize3'])
train_df['wap4'] = (train_df['n_bid4'] * train_df['n_bsize4'] + train_df['n_ask4'] * train_df['n_asize4']) / (train_df['n_bsize4'] + train_df['n_asize4'])

# 计算价格差异百分比(price spread)以及相关特征
train_df['price_spread_2'] = (train_df['n_ask2'] - train_df['n_bid2']) / ((train_df['n_ask2'] + train_df['n_bid2']) / 2)
train_df['price_spread_3'] = (train_df['n_ask3'] - train_df['n_bid3']) / ((train_df['n_ask3'] + train_df['n_bid3']) / 2)
train_df['price_spread_4'] = (train_df['n_ask4'] - train_df['n_bid4']) / ((train_df['n_ask4'] + train_df['n_bid4']) / 2)

# 当前时间特征
# 围绕买卖价格和买卖量进行构建
train_df['wap_balance_23'] = abs(train_df['wap2'] - train_df['wap3'])  # 加权平均价格差异
train_df['bid_spread_23'] = train_df['n_bid2'] - train_df['n_bid3']  # 买入价差
train_df['ask_spread_23'] = train_df['n_ask2'] - train_df['n_ask3']  # 卖出价差
train_df['total_volume_23'] = (train_df['n_asize2'] + train_df['n_asize3']) + (train_df['n_bsize2'] + train_df['n_bsize3'])  # 总交易量
train_df['volume_imbalance_23'] = abs((train_df['n_asize2'] + train_df['n_asize3']) - (train_df['n_bsize2'] + train_df['n_bsize3']))  # 交易量差异

# 围绕买卖价格和买卖量进行构建
# 对于 train_df
train_df['wap_balance_34'] = abs(train_df['wap3'] - train_df['wap4'])  # 加权平均价格差异
train_df['bid_spread_34'] = train_df['n_bid3'] - train_df['n_bid4']  # 买入价差
train_df['ask_spread_34'] = train_df['n_ask3'] - train_df['n_ask4']  # 卖出价差
train_df['total_volume_34'] = (train_df['n_asize3'] + train_df['n_asize4']) + (train_df['n_bsize3'] + train_df['n_bsize4'])  # 总交易量
train_df['volume_imbalance_34'] = abs((train_df['n_asize3'] + train_df['n_asize4']) - (train_df['n_bsize3'] + train_df['n_bsize4']))  # 交易量差异

        可以看到这里我只构建了二、三、四价的特征信息,而并没有构建五价的信息,我尝试了一下在构建相关特征信息之后线下训练直接过拟合了(达到了0.9+),可能和预测的label5有关,故在此处就不建议放入五价的更多信息。

(2)增加二、三、四价的平移、差分、窗口统计特征

# 历史平移
# 获取历史信息
for val in ['wap2','wap3','wap_balance_23','price_spread_2','bid_spread_23','ask_spread_23','total_volume_23','volume_imbalance_23']:
    for loc in [1,5,10,20,40,60]:
        train_df[f'file_{val}_shift{loc}'] = train_df.groupby(['file'])[val].shift(loc)
        test_df[f'file_{val}_shift{loc}'] = test_df.groupby(['file'])[val].shift(loc)
    
# 差分特征
# 获取与历史数据的增长关系
for val in ['wap2','wap3','wap_balance_23','price_spread_2','bid_spread_23','ask_spread_23','total_volume_23','volume_imbalance_23']:
    for loc in [1,5,10,20,40,60]:
        train_df[f'file_{val}_diff{loc}'] = train_df.groupby(['file'])[val].diff(loc)
        test_df[f'file_{val}_diff{loc}'] = test_df.groupby(['file'])[val].diff(loc)
    
# 窗口统计
# 获取历史信息分布变化信息
# 可以尝试更多窗口大小已经统计方式,如min、max、median等
for val in ['wap2','wap3','wap_balance_23','price_spread_2','bid_spread_23','ask_spread_23','total_volume_23','volume_imbalance_23']:
    train_df[f'file_{val}_win7_mean'] = train_df.groupby(['file'])[val].transform(lambda x: x.rolling(window=7, min_periods=3).mean())
    train_df[f'file_{val}_win7_std'] = train_df.groupby(['file'])[val].transform(lambda x: x.rolling(window=7, min_periods=3).std())
    
    test_df[f'file_{val}_win7_mean'] = test_df.groupby(['file'])[val].transform(lambda x: x.rolling(window=7, min_periods=3).mean())
    test_df[f'file_{val}_win7_std'] = test_df.groupby(['file'])[val].transform(lambda x: x.rolling(window=7, min_periods=3).std())

         因代码过多故只展示加入的二价信息,后面三价、四价信息一样。

2. 增加时间信息统计

       观察数据可以看到一共用户(uuid)含有多条会话,因此可以根据uuid进行分组进行统计数值型的特征信息。

        通过计算描述性统计指标来为数据集中的数值列生成新的特征

        首先,通过定义一个包含数值列名称的列表,确定了需要进行统计的特征。

        然后,对于每个唯一的'uuid'标识,代码迭代地组合每个数值列和'uuid',然后针对这些组合,在原始数据集中进行分组。

        接下来,通过计算这些分组内数值列的描述性统计指标,例如均值、标准差、最小值、中位数等,来得出有关这些数值列分布和特征的信息。

        最后,将计算得到的统计特征合并回原始数据集,以丰富数据的特征表示,为后续的建模分析提供更多有价值的信息。

# 定义需要进行描述性统计的数值列
num_cols = [['wap1', 'wap2', 'wap3', 'wap4',
            'price_spread', 'price_spread_2', 'price_spread_3', 'price_spread_4',
            'wap_balance', 'bid_spread', 'ask_spread', 'total_volume', 'volume_imbalance']]

# 针对每个 'uuid' 进行统计特征的计算
b = ['uuid']
for i in b:
    global_dense_group_feature = []
    
    # 构建特征组合列表,包含 'uuid' 和 num_cols 中的每个数值列
    for j in num_cols:
        global_dense_group_feature.append([i, j])

    # 对于每个 [key, value] 组合,进行统计特征的计算
    for [key, value] in tqdm(global_dense_group_feature):
        # 对数据按 'uuid' 分组,计算描述性统计指标,并重新命名列
        tmp = train_df.groupby([key])[value].describe().reset_index()
        tmp.columns = [key] + [key + '_' + value + '_' + x for x in ['count', 'mean', 'std', 'min', '25%', '50%', '75%', 'max']]
        
        # 将计算得到的统计特征合并回原始数据集中
        train_df = train_df.merge(tmp[[key] + [key + '_' + value + '_' + x for x in ['mean', 'std', 'min', '25%', '50%', '75%', 'max']]], on=key, how='left')

 3. 增加更多的窗口滑窗以及统计信息

        计算在不同时间窗口内的一些统计量,包括均值、标准差、中位数、最小值、最大值、百分位数(例如25%和75%分位数),以及移动平均线(例如指数加权移动平均)

        这些统计量是在每个文件组内进行计算,通过滚动窗口或指数加权移动平均的方式,考虑了最近的数据点,并将计算结果添加到原始DataFrame中,以补充原始特征数据。

        这些可以帮助分析数据的趋势、波动性和分布情况,为进一步的数据分析和建模提供更多信息。

for val in fea_cols:
    for time in [3, 10, 20]:
        # 均值
        train_df[f'file_{val}_win{time}_mean'] = train_df.groupby(['file'])[val].transform(lambda x: x.rolling(window=time, min_periods=3).mean())
        # 标准差
        train_df[f'file_{val}_win{time}_std'] = train_df.groupby(['file'])[val].transform(lambda x: x.rolling(window=time, min_periods=3).std()) 
        # 中位数
        train_df[f'file_{val}_win{time}_median'] = train_df.groupby(['file'])[val].transform(lambda x: x.rolling(window=time, min_periods=3).median())
        # 最小值
        train_df[f'file_{val}_win{time}_min'] = train_df.groupby(['file'])[val].transform(lambda x: x.rolling(window=time, min_periods=3).min())
        # 最大值
        train_df[f'file_{val}_win{time}_max'] = train_df.groupby(['file'])[val].transform(lambda x: x.rolling(window=time, min_periods=3).max())
        # 25% 分位数
        train_df[f'file_{val}_win{time}_pct25'] = train_df.groupby(['file'])[val].transform(lambda x: x.rolling(window=time, min_periods=3).quantile(0.25))
        # 75% 分位数
        train_df[f'file_{val}_win{time}_pct75'] = train_df.groupby(['file'])[val].transform(lambda x: x.rolling(window=time, min_periods=3).quantile(0.75))
        # 指数加权移动平均
        train_df[f'file_{val}_win{time}_ema'] = train_df.groupby(['file'])[val].transform(lambda x: x.ewm(span=time, min_periods=3).mean())
        

二、特征筛选方案

1. 相关性筛选特征

        检测列中是否包含具有相同值或缺失值过多的特征。对于具有唯一值数量为1的列,这些特征被认为在建模中没有意义

        检测相关系数矩阵中存在高于指定阈值的相关性的特征。通过计算数据的相关系数矩阵,代码遍历矩阵的每个元素,比较其绝对值与给定阈值。如果某个元素的绝对值大于阈值,就意味着相应的两个特征之间存在高相关性

print('过滤异常特征... ')
drop_cols = []  # 用于存储需要删除的异常特征列的列表
# 遍历DataFrame `df` 的每一列
for col in df.columns:
    # 如果列中的唯一值数量为1,说明该列中所有的值都相同,对于建模来说没有意义,将其添加到 `drop_cols` 列表中
    if df[col].nunique() == 1:
        drop_cols.append(col)
    # 计算每列缺失值的比例,如果缺失值比例超过总行数的 95%,也将该列添加到 `drop_cols` 列表中
    if df[col].isnull().sum() / df.shape[0] > 0.95:
        drop_cols.append(col)

print('过滤高相关特征...')
# 定义一个函数用于检测高相关特征
def correlation(data, threshold):
    col_corr = []  # 用于存储高相关特征列的列表
    corr_matrix = data.corr()  # 计算数据的相关系数矩阵
    # 遍历相关系数矩阵中的每个元素
    for i in range(len(corr_matrix)):
        for j in range(i):
            # 如果某个元素的绝对值大于阈值 `threshold`,说明这两个特征之间存在高相关性
            # 将其中一个特征的名称添加到 `col_corr` 列表中
            if abs(corr_matrix.iloc[i, j]) > threshold:
                colname = corr_matrix.columns[i]
                col_corr.append(colname)
    return list(set(col_corr))  # 返回包含所有高相关特征的列名的列表

2. 特征重要性筛选特征

        在特征选择的背景下,通过训练CatBoost分类器模型并分析特征重要性,确定哪些特征对于解决给定的分类问题最为重要。它将模型训练和特征选择结合在一起,以便找到对模型性能有显著贡献的特征,从而优化建模过程并提高预测的准确性


def model_train(x_train, y_train, x_test, y_test):
    params = {'learning_rate': 0.2, 'depth': 12, 'bootstrap_type':'Bernoulli','random_seed':2023,
                      'od_type': 'Iter', 'od_wait': 100, 'random_seed': 23, 'allow_writing_files': False,
                      'loss_function': 'MultiClass'}
    model = CatBoostClassifier(iterations=5000, **params)
    model.fit(x_train, y_train, eval_set=(x_test, y_test),
                metric_period=100,
                use_best_model=True, 
                cat_features=[],
                verbose=1)
    return model

def select_feature(train_df, feature_name, pred):
    # 数据划分
    x_train, x_test, y_train, y_test = train_test_split(train_df[feature_name], train_df[pred], test_size=0.25, random_state=23)
    # 将数据编号进行重编号
    x_train, y_train = x_train.reset_index(drop=True), y_train.reset_index(drop=True)
    x_test, y_test = x_test.reset_index(drop=True), y_test.reset_index(drop=True)
    cat_model = model_train(x_train, y_train, x_test, y_test)
    df = pd.DataFrame({'feature': x_train.columns, 'importance': cat_model.feature_importances_}).sort_values(
        by='importance', ascending=False)  # 降序
    use = df.loc[df['importance'] != 0, 'feature'].tolist()
    print('有用的特征个数:', len(use))
    # print('有用的特征:', use)
    return use

3.使用对抗训练筛选特征

         对抗训练在特征选择中是一种基于模型的方法,它通过在特征子集上构建对抗性模型,使得这些模型难以区分正常数据和噪声数据,从而筛选出对模型更具挑战性的特征。这样的方法可以鼓励模型学习更具鲁棒性的特征,同时抑制噪声对特征选择的影响

# 划分数据为特征和目标
X = train_df.drop(columns=['target'])
y = train_df['target']

# 划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 使用 CatBoost 模型构建分类器
model = CatBoostClassifier(iterations=500, learning_rate=0.1, depth=8, random_seed=42)
model.fit(X_train, y_train, eval_set=(X_test, y_test), verbose=100)

# 提取特征重要性
feature_importances = model.get_feature_importance()

# 排序特征重要性
sorted_indices = np.argsort(feature_importances)[::-1]

# 选择前N个重要的特征
num_selected_features = 10
selected_feature_indices = sorted_indices[:num_selected_features]
selected_features = X.columns[selected_feature_indices]

print("Selected features:", selected_features)

4. feature-selection-with-null-importances

通过对数据的随机置换来构建一组基准分布,以评估每个特征在模型中的实际重要性

  • 首先,从 提供的数据集中读取数据,并进行预处理和准备。
  • 使用 CatBoost 模型构建一个基准模型,将原始数据拟合到模型中。
  • 通过对每个特征进行随机置换,对特征进行重要性评估。随机置换会破坏特征与目标之间的关系,从而产生一个“空”或“虚假”的特征重要性分布。
  • 计算原始特征与随机置换特征重要性之间的差异,以识别出真正对目标有贡献的特征。这些差异指示了模型在原始特征上的学习能力。
  • 结合原始特征重要性和虚假特征重要性分布,生成一个重要性置信度分数。较高的置信度分数表示特征对目标的贡献更加显著。
  • 基于特征的重要性置信度分数,筛选出最有价值的特征,用于进一步的建模和分析。

        通过这种基于空重要性的方法,该方案可以在特征选择过程中综合考虑特征与目标之间的关系以及模型的学习能力,从而识别出对于解决问题最为关键的特征,提高了模型的预测能力和可解释性。

实现方案链接

 Feature Selection with Null Importances | Kaggle

 三、内存压缩

        比赛按照上面的baseline会读取很大的数据内存,因此在此处放入一个降低内存的方法:

        通过减少数字列的数据类型并将对象列转换为分类类型来优化 DataFrame 'train_df' 的内存使用量,从而减少内存使用量。

# 定义一个列表,其中包含需要进行内存优化的特征列(排除 'uuid'、'time' 和 'file' 列)
predictor_columns = [col for col in test_df.columns if col not in ['uuid','time','file']]

# 定义内存优化函数,用于减少数据帧的内存使用量
def reduce_mem_usage(df):
    # 计算初始内存使用量
    start_mem = df.memory_usage().sum() / 1024**2
    print('Memory usage of dataframe is {:.2f} MB'.format(start_mem))
    
    # 遍历预测特征列
    for col in tqdm.tqdm(predictor_columns):
        col_type = df[col].dtype
        
        # 根据特征列的数据类型进行优化
        if col_type != object:
            c_min = df[col].min()
            c_max = df[col].max()
            
            # 根据数据范围选择适当的数据类型
            if str(col_type)[:3] == 'int':
                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
                    df[col] = df[col].astype(np.int8)
                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
                    df[col] = df[col].astype(np.int16)
                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
                    df[col] = df[col].astype(np.int32)
                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
                    df[col] = df[col].astype(np.int64)
            else:
                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
                    df[col] = df[col].astype(np.float16)
                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
                    df[col] = df[col].astype(np.float32)
                else:
                    df[col] = df[col].astype(np.float64)
        else:
            df[col] = df[col].astype('category')
    
    # 计算优化后的内存使用量
    end_mem = df.memory_usage().sum() / 1024**2
    print('Memory usage after optimization is: {:.2f} MB'.format(end_mem))
    print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))
    return df

# 调用内存优化函数,对训练数据帧进行内存优化
train_df = reduce_mem_usage(train_df)

四、验证方式

1. 交叉验证

        交叉验证是一种评估机器学习模型性能的技术,用于估计模型在未见过的数据上的表现。其基本思想是将原始数据集分成若干个子集(折),然后重复多次,每次将其中一折作为验证集,其余折作为训练集。这样可以对模型进行多次训练和验证,从而更全面地评估模型的性能。

在交叉验证过程中,每次迭代的步骤如下:

  • 将数据集分成k个子集,通常称为“折”(folds)。
  • 在每次迭代中,选择其中一个折作为验证集,其余折作为训练集。
  • 使用训练集训练模型,然后在验证集上进行预测,得到模型的性能指标。
  • 重复以上步骤k次,每次选择不同的验证集。
  • 计算k次迭代中性能指标的平均值,作为最终的模型性能评估。

常见的交叉验证方法包括 k 折交叉验证(k-Fold Cross Validation)、留一交叉验证(Leave-One-Out Cross Validation,LOOCV)以及随机分割交叉验证等。交叉验证可以帮助评估模型在不同数据子集上的泛化能力,降低过拟合的风险,提供对模型性能的更准确估计,以便更好地调整模型参数或选择最佳模型。

2. 时序验证

        时序验证是一种特殊的交叉验证方法,专门针对时间序列数据的模型评估。在时间序列数据中,数据点的顺序对于模型的训练和验证至关重要,因为未来的数据点可能受过去数据点的影响。时序验证方法能够在保留时间顺序的前提下,对时间序列数据进行模型评估,更好地模拟模型在实际应用中的性能。

        时序验证的基本思想是将时间序列数据划分为训练集和测试集,其中测试集的时间窗口在训练集之后。这样可以模拟模型在未来数据上的预测能力。常见的时序验证方法包括滚动窗口验证(Rolling Window Validation)和时间分割验证(Time-based Split Validation)等。

在滚动窗口验证中,训练集的时间窗口逐步向前滑动,每次增加一个时间步长,以便在不同时间段对模型进行训练和验证。在时间分割验证中,将时间序列数据按照时间顺序划分为多个时间段,每个时间段作为一个验证集,其之前的数据作为训练集。

五、模型集成

1. 多模型加权融合

        模型加权融合是一种集成学习方法,旨在通过将多个不同算法或同一算法的不同实例的预测结果进行加权组合,从而提高模型的预测性能和稳定性。在加权融合中,每个模型的权重根据其在训练集上的表现或其他评估指标而定,较优的模型获得更高的权重。这种方法能够平衡各个模型的优势,弥补单一模型的不足,从而在多个模型的共同作用下,产生更准确、鲁棒的预测结果。加权融合适用于提升预测效果、减小过拟合风险以及对多种算法进行有效组合的情境。

 2. stacking模型融合

        Stacking(又称为堆叠)是一种集成学习方法,用于将多个基本模型(也称为初级模型或基分类器)的预测结果作为输入,通过训练一个次级模型(也称为元模型或次级分类器)来生成最终的预测结果。Stacking 通过将不同模型的预测结果结合起来,可以有效地提高模型的预测性能和泛化能力。

 

from sklearn.model_selection import RepeatedKFold
def stack_model(oof_1, oof_2, oof_3, predictions_1, predictions_2, predictions_3, y):
    # 合并训练集的预测结果
    train_stack = pd.concat([oof_1, oof_2, oof_3], axis=1)
    # 合并测试集的预测结果
    test_stack = pd.concat([predictions_1, predictions_2, predictions_3], axis=1)
    # 初始化一个全零数组来存储最终的交叉验证预测结果
    oof = np.zeros((train_stack.shape[0],))
    # 初始化一个全零数组来存储最终的测试集预测结果
    predictions = np.zeros((test_stack.shape[0],))
    # 存储每个交叉验证折数的模型分数
    scores = []
    # 定义交叉验证折数和重复次数,用于后续交叉验证的划分
    folds = RepeatedKFold(n_splits=5, n_repeats=2, random_state=2021)
    for fold_, (trn_idx, val_idx) in enumerate(folds.split(train_stack, y)):
        print("第{}折交叉验证".format(fold_+1))
        # 获取当前折数的训练数据和标签
        trn_data, trn_y = train_stack.loc[trn_idx], y[trn_idx]
        # 获取当前折数的验证数据和标签
        val_data, val_y = train_stack.loc[val_idx], y[val_idx]
        # 初始化回归模型
        clf = Ridge(random_state=2021)
        # 在当前折数的训练数据上拟合模型
        clf.fit(trn_data, trn_y)
        # 对当前折数的验证数据进行预测
        oof[val_idx] = clf.predict(val_data)
        # 对测试集进行预测,并累加预测结果(最后会取平均值)
        predictions += clf.predict(test_stack) / (5 * 2)
        # 计算当前折数的验证集的ROC AUC得分
        score_single = roc_auc_score(val_y, oof[val_idx])
        # 将当前折数得分添加到scores列表中
        scores.append(score_single)
        print(f'{fold_+1}/5', score_single)
    # 输出交叉验证得分的平均值
    print('mena:', np.mean(scores))
    # 返回交叉验证预测结果和测试集预测结果
    return oof, predictions

 科大讯飞AI量化模型预测挑战赛_Baseline - 飞桨AI Studio (baidu.com)

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

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

相关文章

BC260模块_NB通讯_MQTT

闲来无事从角落里找出了一个BC260模块&#xff0c;玩了玩发现挺有趣的&#xff0c;于是将调试过程记录下来分享给需要的朋友们。 1.BC260模块 BC260模块是一款NB-loT无线通讯模块&#xff0c;模块插上物联网SIM卡后可以实现物联网无线通讯功能。 BC260模块是一款NB-loT无线通…

android 开发中常用命令

1.反编译 命令&#xff1a;apktool d <test.apk> -o <folderdir> 其中&#xff1a;test.apk是待反编译文件的路径&#xff0c;folderdir是反编译后的文件的存储位置。 apktool d -f <test.apk> -o <folderdir> 注意&#xff1a;如果dir已经存在&am…

2023年测试岗,软件测试面试题汇总-附答案,疯狂拿offer...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 介绍一下测试流程…

共享式以太网的争用期

在以太网中&#xff0c;必然会发生碰撞。   站点从发送帧开始&#xff0c;最多经过 2 τ 2\tau 2τ就会检测到碰撞&#xff0c;此时 2 τ 2\tau 2τ被称为争用期或碰撞窗口。   站点从发送帧开始&#xff0c;经过争用期 2 τ 2\tau 2τ这段时间还没有检测到碰撞&#xff0c…

不只是Axure,这5 个也能轻松画原型图!

在设计和开发过程中&#xff0c;原型图是一个至关重要的工具。它是将设计理念转化为可视化、交互式的形式&#xff0c;使团队成员和利益相关者更好地理解和评估产品的功能和用户体验。选择适合的软件工具对于画原型图至关重要&#xff0c;本文将介绍 5 种常用的画原型图软件&am…

创建Springboot+vue3项目

项目概述创建springboot项目加入mybatis-plus支持1.加入依赖代码2.创建数据库实例3.yml文件的配置4.编写测试代码5.测试结果 创建vue项目报错错误一错误二错误三 项目概述 后端&#xff1a;Springboot、mybatis-plus、java 前端&#xff1a;nodejs、vue脚手架、element-ui 数据…

互联网医院|线上医疗平台连接医者和患者的桥梁

近年来&#xff0c;随着互联网技术的飞速发展&#xff0c;互联网医院系统悄然崛起&#xff0c;引领着医疗行业的变革浪潮。这一系统以其出色的功能与服务&#xff0c;为广大患者带来了便捷、高效的医疗体验&#xff0c;将传统医疗模式推向了新的高度。 作为医疗界的新生力量&a…

计算机网络—IP

这里写目录标题 IP的基本认识网络层与数据链路层有什么关系IP地址基础知识IP 地址的分类什么是A、B、C类地址广播地址用来做什么什么是D、E类广播多播地址用于什么IP分类的优点IP分类的缺点 无分类地址CIDR如何划分网络号和主机号怎么进性子网划分 公有 IP 地址与私有 IP 地址公…

sentinel客户端和dashboard交互

回顾 在前面的章节中&#xff1a;通过阐述sentinel简单使用、滑动窗口、核心流程源码分析把sentinel限流、熔断等主要功能说明清楚了&#xff0c;但我们在实际使用的过程中&#xff0c;不可能通过硬编码的方式设置规则&#xff0c;且规则也没法直观的维护&#xff0c;为此肯定…

如何在 Cloudron 上部署 ONLYOFFICE 文档

使用 Cloudron 应用市场上的应用程序&#xff0c;只需点击几下即可在服务器上部署 ONLYOFFICE 文档。 什么是 ONLYOFFICE 文档 ONLYOFFICE 文档是一个在线办公套件&#xff0c;包括文本文档、电子表格和演示文稿的查看器和编辑器&#xff0c;与包括 .docx、.xlsx、.pptx 在内的…

八、复用(1)

本章概要 组合语法继承语法 初始化基类带参数的构造函数 委托 代码复用是面向对象编程&#xff08;OOP&#xff09;最具魅力的原因之一。 对于像 C 语言等面向过程语言来说&#xff0c;“复用”通常指的就是“复制代码”。任何语言都可通过简单复制来达到代码复用的目的&#…

Hive终端命令行打印很多日志时,如何设置日志级别

示例&#xff1a;use test; 切换到test数据库时&#xff0c;输出很多日志信息不方便看结果&#xff0c;如下图。 解决方法&#xff1a; 退出hive命令行界面&#xff08;ctrlC&#xff09;执行“vi /usr/local/apache-hive-3.1.2-bin/conf/log4j.properties”命令&#xff0c;创…

AI lightning学习

真的是没有mmlab的框架好理解&#xff0c;hook调用没问题&#xff0c;就是代码写的不整洁&#xff0c;hook放的到处都是&#xff0c;而且hook的名字和run的名字也不好对应。 又是捧mmengine的一天 &#x1f603;

《面试1v1》ElasticSearch 集群索引分片

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

React中使用mobx管理状态数据使用样例

MobX 是一个身经百战的库&#xff0c;它通过运用透明的函数式响应编程&#xff08;Transparent Functional Reactive Programming&#xff0c;TFRP&#xff09;使状态管理变得简单和可扩展。官网地址&#xff1a;关于 MobX | MobX中文文档 | MobX中文网 安装依赖 mobx-react-…

共享式以太网的退避算法

在使用CSMA/CD协议的共享总线以太网中&#xff0c;正在发送顿的站点一边发送顿一边检测碰撞&#xff0c;当检测到碰撞时就立即停止发送&#xff0c;退避一段随机时间后再重新发送。   截断二进制指数退避算法&#xff1a;退避时间基本退避时间 2 τ 2\tau 2τ随机数r{ 0 , 1 …

Java笔记(三十二):MySQL(下)-- 事务、索引、引擎、视图、MySQL管理

七、事务transaction 1、引入 场景&#xff1a;学工部整个部门解散了&#xff0c;该部门及部门下的员工都需要删除了。 操作&#xff1a; -- 删除学工部 delete from dept where id 1; -- 删除成功-- 删除学工部的员工 delete from emp where dept_id 1; -- 删除失败&…

Java从入门到精通(四)· 面向对象

Java从入门到精通&#xff08;四&#xff09; 面向对象 一 静态关键字&#xff08;static&#xff09; static表示静态关键字&#xff0c;可以用来修饰成员变量和成员方法。 被 static修饰的成员变量&#xff0c;称之为静态成员变量或者类变量&#xff0c;同理可得&#xff…

前端性能优化介绍与常见方法(二)

这是一个没有套路的前端博主&#xff0c;热衷各种前端向的骚操作&#xff0c;经常想到哪就写到哪&#xff0c;如果有感兴趣的技术和前端效果可以留言&#xff5e;博主看到后会去代替大家踩坑的&#xff5e; 主页: oliver尹的主页 格言: 跌倒了爬起来就好&#xff5e; 目录 一、…

条件竞争漏洞Double Fetch

前言 Double Fetch(双取)是一种条件竞争的漏洞&#xff0c;相关的论文发表在USENIX&#xff0c;论文链接&#xff1a;https://www.usenix.org/system/files/conference/usenixsecurity17/sec17-wang.pdf Double Fetch Double Fetch是内核的一种漏洞类型&#xff0c;发生在内…