当前位置: 首页 > news >正文

政安晨:【Keras机器学习示例演绎】(五十七)—— 基于Transformer的推荐系统

目录

介绍

数据集

设置

准备数据

将电影评分数据转换为序列

定义元数据

创建用于训练和评估的 tf.data.Dataset

创建模型输入

输入特征编码

创建 BST 模型

开展培训和评估实验


政安晨的个人主页:政安晨

欢迎 👍点赞✍评论⭐收藏

希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正!

本文目标:在 Movielens 上使用行为序列转换器(BST)模型预测评级率。

介绍

本示例使用 Movielens 数据集演示了陈启伟等人的行为序列转换器(BST)模型。 BST 模型利用用户观看电影和给电影评分的顺序行为,以及用户资料和电影特征,来预测用户对目标电影的评分。

更确切地说,BST 模型旨在通过接受以下输入来预测目标电影的评分:

  1. 用户观看过的电影的固定长度序列。
  2. 用户观看过的电影评分的固定长度序列。
  3. 输入序列中每部电影和目标电影的类型集。
  4. 输入序列中每部电影和目标电影的类型集。
  5. 要预测评分的 target_movie_id。

该示例以下列方式修改了原始 BST 模型:

1. 我们在处理输入序列中的每部电影和目标电影的嵌入过程中都加入了电影特征(流派),而不是将其视为转换层之外的 "其他特征"。

2. 我们利用输入序列中电影的评分以及它们在序列中的位置来更新它们,然后再将它们输入自我关注层。

请注意,本示例应在 TensorFlow 2.4 或更高版本中运行。

数据集

我们使用的是 Movielens 数据集的 1M 版本。 该数据集包含 6000 名用户对 4000 部电影的约 100 万个评分,以及一些用户特征和电影类型。 此外,数据集还提供了每个用户对电影评分的时间戳,这样就可以按照 BST 模型的预期,为每个用户创建电影评分序列。

设置

import osos.environ["KERAS_BACKEND"] = "tensorflow"import math
from zipfile import ZipFile
from urllib.request import urlretrieveimport keras
import numpy as np
import pandas as pd
import tensorflow as tf
from keras import layers
from keras.layers import StringLookup

准备数据

下载并准备数据框

首先,让我们下载 movielens 数据。

下载的文件夹将包含三个数据文件:users.dat、movies.dat 和 ratings.dat。

urlretrieve("http://files.grouplens.org/datasets/movielens/ml-1m.zip", "movielens.zip")
ZipFile("movielens.zip", "r").extractall()

然后,我们用正确的列名将数据加载到 pandas DataFrames 中。

users = pd.read_csv("ml-1m/users.dat",sep="::",names=["user_id", "sex", "age_group", "occupation", "zip_code"],encoding="ISO-8859-1",engine="python",
)ratings = pd.read_csv("ml-1m/ratings.dat",sep="::",names=["user_id", "movie_id", "rating", "unix_timestamp"],encoding="ISO-8859-1",engine="python",
)movies = pd.read_csv("ml-1m/movies.dat",sep="::",names=["movie_id", "title", "genres"],encoding="ISO-8859-1",engine="python",
)

在此,我们进行一些简单的数据处理,以固定列的数据类型。

users["user_id"] = users["user_id"].apply(lambda x: f"user_{x}")
users["age_group"] = users["age_group"].apply(lambda x: f"group_{x}")
users["occupation"] = users["occupation"].apply(lambda x: f"occupation_{x}")movies["movie_id"] = movies["movie_id"].apply(lambda x: f"movie_{x}")ratings["movie_id"] = ratings["movie_id"].apply(lambda x: f"movie_{x}")
ratings["user_id"] = ratings["user_id"].apply(lambda x: f"user_{x}")
ratings["rating"] = ratings["rating"].apply(lambda x: float(x))

每部电影都有多种类型。 我们将它们分成电影 DataFrame 中的不同列。

genres = ["Action", "Adventure", "Animation", "Children's", "Comedy", "Crime"]
genres += ["Documentary", "Drama", "Fantasy", "Film-Noir", "Horror", "Musical"]
genres += ["Mystery", "Romance", "Sci-Fi", "Thriller", "War", "Western"]for genre in genres:movies[genre] = movies["genres"].apply(lambda values: int(genre in values.split("|")))

将电影评分数据转换为序列

首先,我们使用 unix_timestamp 对评分数据进行排序,然后按用户 ID 对电影 ID 值和评分值进行分组。

ratings_group = ratings.sort_values(by=["unix_timestamp"]).groupby("user_id")ratings_data = pd.DataFrame(data={"user_id": list(ratings_group.groups.keys()),"movie_ids": list(ratings_group.movie_id.apply(list)),"ratings": list(ratings_group.rating.apply(list)),"timestamps": list(ratings_group.unix_timestamp.apply(list)),}
)

现在,让我们把 movie_ids 列表拆分成一组固定长度的序列。 我们对评分也做同样的处理。 设置 sequence_length 变量可改变模型输入序列的长度。 您还可以改变 step_size 来控制为每个用户生成的序列数量。

sequence_length = 4
step_size = 2def create_sequences(values, window_size, step_size):sequences = []start_index = 0while True:end_index = start_index + window_sizeseq = values[start_index:end_index]if len(seq) < window_size:seq = values[-window_size:]if len(seq) == window_size:sequences.append(seq)breaksequences.append(seq)start_index += step_sizereturn sequencesratings_data.movie_ids = ratings_data.movie_ids.apply(lambda ids: create_sequences(ids, sequence_length, step_size)
)ratings_data.ratings = ratings_data.ratings.apply(lambda ids: create_sequences(ids, sequence_length, step_size)
)del ratings_data["timestamps"]

然后,我们对输出进行处理,使每个序列在 DataFrame 中都有单独的记录。 此外,我们还将用户特征与评分数据结合起来。

ratings_data_movies = ratings_data[["user_id", "movie_ids"]].explode("movie_ids", ignore_index=True
)
ratings_data_rating = ratings_data[["ratings"]].explode("ratings", ignore_index=True)
ratings_data_transformed = pd.concat([ratings_data_movies, ratings_data_rating], axis=1)
ratings_data_transformed = ratings_data_transformed.join(users.set_index("user_id"), on="user_id"
)
ratings_data_transformed.movie_ids = ratings_data_transformed.movie_ids.apply(lambda x: ",".join(x)
)
ratings_data_transformed.ratings = ratings_data_transformed.ratings.apply(lambda x: ",".join([str(v) for v in x])
)del ratings_data_transformed["zip_code"]ratings_data_transformed.rename(columns={"movie_ids": "sequence_movie_ids", "ratings": "sequence_ratings"},inplace=True,
)

在 sequence_length 为 4、step_size 为 2 的情况下,我们最终得到了 498 623 个序列。 最后,我们将数据分成训练和测试两个部分,分别包含 85% 和 15% 的实例,并将它们存储到 CSV 文件中。

random_selection = np.random.rand(len(ratings_data_transformed.index)) <= 0.85
train_data = ratings_data_transformed[random_selection]
test_data = ratings_data_transformed[~random_selection]train_data.to_csv("train_data.csv", index=False, sep="|", header=False)
test_data.to_csv("test_data.csv", index=False, sep="|", header=False)

定义元数据

CSV_HEADER = list(ratings_data_transformed.columns)CATEGORICAL_FEATURES_WITH_VOCABULARY = {"user_id": list(users.user_id.unique()),"movie_id": list(movies.movie_id.unique()),"sex": list(users.sex.unique()),"age_group": list(users.age_group.unique()),"occupation": list(users.occupation.unique()),
}USER_FEATURES = ["sex", "age_group", "occupation"]MOVIE_FEATURES = ["genres"]

创建用于训练和评估的 tf.data.Dataset

def get_dataset_from_csv(csv_file_path, shuffle=False, batch_size=128):def process(features):movie_ids_string = features["sequence_movie_ids"]sequence_movie_ids = tf.strings.split(movie_ids_string, ",").to_tensor()# The last movie id in the sequence is the target movie.features["target_movie_id"] = sequence_movie_ids[:, -1]features["sequence_movie_ids"] = sequence_movie_ids[:, :-1]ratings_string = features["sequence_ratings"]sequence_ratings = tf.strings.to_number(tf.strings.split(ratings_string, ","), tf.dtypes.float32).to_tensor()# The last rating in the sequence is the target for the model to predict.target = sequence_ratings[:, -1]features["sequence_ratings"] = sequence_ratings[:, :-1]return features, targetdataset = tf.data.experimental.make_csv_dataset(csv_file_path,batch_size=batch_size,column_names=CSV_HEADER,num_epochs=1,header=False,field_delim="|",shuffle=shuffle,).map(process)return dataset

创建模型输入

def create_model_inputs():return {"user_id": keras.Input(name="user_id", shape=(1,), dtype="string"),"sequence_movie_ids": keras.Input(name="sequence_movie_ids", shape=(sequence_length - 1,), dtype="string"),"target_movie_id": keras.Input(name="target_movie_id", shape=(1,), dtype="string"),"sequence_ratings": keras.Input(name="sequence_ratings", shape=(sequence_length - 1,), dtype=tf.float32),"sex": keras.Input(name="sex", shape=(1,), dtype="string"),"age_group": keras.Input(name="age_group", shape=(1,), dtype="string"),"occupation": keras.Input(name="occupation", shape=(1,), dtype="string"),}

输入特征编码

输入特征编码方法的工作原理如下:

每个分类用户特征都使用层嵌入(layer.Embedding)编码,嵌入维度等于特征词汇量的平方根。

电影序列中的每部电影和目标电影都使用层.嵌入编码,嵌入维度等于电影数量的平方根。

每部电影的多热点流派向量与其嵌入向量连接,并使用非线性层.密集处理,以输出具有相同电影嵌入维度的向量。
将位置嵌入添加到序列中的每个电影嵌入中,然后乘以评分序列中的评分。

将目标电影嵌入与序列电影嵌入连接起来,产生一个张量,其形状为[批量大小、序列长度、嵌入大小],正如转换器架构的注意层所预期的那样。

该方法返回一个由两个元素组成的元组:编码转换器特征和编码其他特征。

def encode_input_features(inputs,include_user_id=True,include_user_features=True,include_movie_features=True,
):encoded_transformer_features = []encoded_other_features = []other_feature_names = []if include_user_id:other_feature_names.append("user_id")if include_user_features:other_feature_names.extend(USER_FEATURES)## Encode user featuresfor feature_name in other_feature_names:# Convert the string input values into integer indices.vocabulary = CATEGORICAL_FEATURES_WITH_VOCABULARY[feature_name]idx = StringLookup(vocabulary=vocabulary, mask_token=None, num_oov_indices=0)(inputs[feature_name])# Compute embedding dimensionsembedding_dims = int(math.sqrt(len(vocabulary)))# Create an embedding layer with the specified dimensions.embedding_encoder = layers.Embedding(input_dim=len(vocabulary),output_dim=embedding_dims,name=f"{feature_name}_embedding",)# Convert the index values to embedding representations.encoded_other_features.append(embedding_encoder(idx))## Create a single embedding vector for the user featuresif len(encoded_other_features) > 1:encoded_other_features = layers.concatenate(encoded_other_features)elif len(encoded_other_features) == 1:encoded_other_features = encoded_other_features[0]else:encoded_other_features = None## Create a movie embedding encodermovie_vocabulary = CATEGORICAL_FEATURES_WITH_VOCABULARY["movie_id"]movie_embedding_dims = int(math.sqrt(len(movie_vocabulary)))# Create a lookup to convert string values to integer indices.movie_index_lookup = StringLookup(vocabulary=movie_vocabulary,mask_token=None,num_oov_indices=0,name="movie_index_lookup",)# Create an embedding layer with the specified dimensions.movie_embedding_encoder = layers.Embedding(input_dim=len(movie_vocabulary),output_dim=movie_embedding_dims,name=f"movie_embedding",)# Create a vector lookup for movie genres.genre_vectors = movies[genres].to_numpy()movie_genres_lookup = layers.Embedding(input_dim=genre_vectors.shape[0],output_dim=genre_vectors.shape[1],embeddings_initializer=keras.initializers.Constant(genre_vectors),trainable=False,name="genres_vector",)# Create a processing layer for genres.movie_embedding_processor = layers.Dense(units=movie_embedding_dims,activation="relu",name="process_movie_embedding_with_genres",)## Define a function to encode a given movie id.def encode_movie(movie_id):# Convert the string input values into integer indices.movie_idx = movie_index_lookup(movie_id)movie_embedding = movie_embedding_encoder(movie_idx)encoded_movie = movie_embeddingif include_movie_features:movie_genres_vector = movie_genres_lookup(movie_idx)encoded_movie = movie_embedding_processor(layers.concatenate([movie_embedding, movie_genres_vector]))return encoded_movie## Encoding target_movie_idtarget_movie_id = inputs["target_movie_id"]encoded_target_movie = encode_movie(target_movie_id)## Encoding sequence movie_ids.sequence_movies_ids = inputs["sequence_movie_ids"]encoded_sequence_movies = encode_movie(sequence_movies_ids)# Create positional embedding.position_embedding_encoder = layers.Embedding(input_dim=sequence_length,output_dim=movie_embedding_dims,name="position_embedding",)positions = tf.range(start=0, limit=sequence_length - 1, delta=1)encodded_positions = position_embedding_encoder(positions)# Retrieve sequence ratings to incorporate them into the encoding of the movie.sequence_ratings = inputs["sequence_ratings"]sequence_ratings = keras.ops.expand_dims(sequence_ratings, -1)# Add the positional encoding to the movie encodings and multiply them by rating.encoded_sequence_movies_with_poistion_and_rating = layers.Multiply()([(encoded_sequence_movies + encodded_positions), sequence_ratings])# Construct the transformer inputs.for i in range(sequence_length - 1):feature = encoded_sequence_movies_with_poistion_and_rating[:, i, ...]feature = keras.ops.expand_dims(feature, 1)encoded_transformer_features.append(feature)encoded_transformer_features.append(encoded_target_movie)encoded_transformer_features = layers.concatenate(encoded_transformer_features, axis=1)return encoded_transformer_features, encoded_other_features

创建 BST 模型

include_user_id = False
include_user_features = False
include_movie_features = Falsehidden_units = [256, 128]
dropout_rate = 0.1
num_heads = 3def create_model():inputs = create_model_inputs()transformer_features, other_features = encode_input_features(inputs, include_user_id, include_user_features, include_movie_features)# Create a multi-headed attention layer.attention_output = layers.MultiHeadAttention(num_heads=num_heads, key_dim=transformer_features.shape[2], dropout=dropout_rate)(transformer_features, transformer_features)# Transformer block.attention_output = layers.Dropout(dropout_rate)(attention_output)x1 = layers.Add()([transformer_features, attention_output])x1 = layers.LayerNormalization()(x1)x2 = layers.LeakyReLU()(x1)x2 = layers.Dense(units=x2.shape[-1])(x2)x2 = layers.Dropout(dropout_rate)(x2)transformer_features = layers.Add()([x1, x2])transformer_features = layers.LayerNormalization()(transformer_features)features = layers.Flatten()(transformer_features)# Included the other features.if other_features is not None:features = layers.concatenate([features, layers.Reshape([other_features.shape[-1]])(other_features)])# Fully-connected layers.for num_units in hidden_units:features = layers.Dense(num_units)(features)features = layers.BatchNormalization()(features)features = layers.LeakyReLU()(features)features = layers.Dropout(dropout_rate)(features)outputs = layers.Dense(units=1)(features)model = keras.Model(inputs=inputs, outputs=outputs)return modelmodel = create_model()

开展培训和评估实验

# Compile the model.
model.compile(optimizer=keras.optimizers.Adagrad(learning_rate=0.01),loss=keras.losses.MeanSquaredError(),metrics=[keras.metrics.MeanAbsoluteError()],
)# Read the training data.
train_dataset = get_dataset_from_csv("train_data.csv", shuffle=True, batch_size=265)# Fit the model with the training data.
model.fit(train_dataset, epochs=5)# Read the test data.
test_dataset = get_dataset_from_csv("test_data.csv", batch_size=265)# Evaluate the model on the test data.
_, rmse = model.evaluate(test_dataset, verbose=0)
print(f"Test MAE: {round(rmse, 3)}")
Epoch 1/51600/1600 ━━━━━━━━━━━━━━━━━━━━ 19s 11ms/step - loss: 1.5762 - mean_absolute_error: 0.9892
Epoch 2/51600/1600 ━━━━━━━━━━━━━━━━━━━━ 17s 11ms/step - loss: 1.1263 - mean_absolute_error: 0.8502
Epoch 3/51600/1600 ━━━━━━━━━━━━━━━━━━━━ 17s 11ms/step - loss: 1.0885 - mean_absolute_error: 0.8361
Epoch 4/51600/1600 ━━━━━━━━━━━━━━━━━━━━ 17s 11ms/step - loss: 1.0943 - mean_absolute_error: 0.8388
Epoch 5/51600/1600 ━━━━━━━━━━━━━━━━━━━━ 17s 10ms/step - loss: 1.0360 - mean_absolute_error: 0.8142
Test MAE: 0.782

测试数据的平均绝对误差 (MAE) 应该在 0.7 左右。


相关文章:

政安晨:【Keras机器学习示例演绎】(五十七)—— 基于Transformer的推荐系统

目录 介绍 数据集 设置 准备数据 将电影评分数据转换为序列 定义元数据 创建用于训练和评估的 tf.data.Dataset 创建模型输入 输入特征编码 创建 BST 模型 开展培训和评估实验 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 希望政安晨的…...

15.4 zookeeper java client之Curator使用(❤❤❤❤❤)

Curator使用 1. 为什么使用Curator对比Zookeeper原生2. 集成Curator2.1 依赖引入curator-frameworkcurator-recipes2.2 `yml`配置连接信息2.3 CuratorConfig配置类2.4 Curator实现Zookeeper分布式锁业务2.4.1 业务:可重入锁和不可重入锁可重入锁和不可重入锁InterProcessMutex …...

哈默纳科HarmonicDrive谐波减速机的使用寿命计算

在机械传动系统中&#xff0c;减速机的应用无处不在&#xff0c;而HarmonicDrive哈默纳科谐波减速机以其独特的优势&#xff0c;如轻量、小型、传动效率高、减速范围广、精度高等特点&#xff0c;成为了众多领域的选择。然而&#xff0c;任何机械设备都有其使用寿命&#xff0c…...

前后端完全分离实现登录和退出

前后端分离的整合 使用springsecurity前端项目redis完成认证授权的代码 1. 搭建一个前端工程 使用 vue ui搭建&#xff0c;使用webstrom操作 2. 创建一个登录页面 <template><div class"login_container"><!-- 登录盒子 --><div class"l…...

生信技能55 - WisecondorX分析结果过滤和质控

WisecondorX分析CNV,对每条染色的CNV loss和gain进行分组,对每个组求ratio平均值和zscore平均值,基于该数值对CNV进行质控和过滤,并对连续的CNV进行合并,获得可信的CNV。 WisecondorX基本使用方法以及npz文件转换和reference构建参考文章: 生信技能53 - wiseconrdoX自动…...

待办管理软件电脑版哪个好?待办事项清单app

在快节奏的现代社会中&#xff0c;有效地管理时间和任务变得越来越重要。很多人喜欢使用待办管理软件来协助整理琐碎事务、规划工作任务&#xff0c;以此提升工作效率。特别是对于上班族来说&#xff0c;一款能在电脑上便捷使用的待办软件&#xff0c;更是提升工作效率的得力助…...

【Mind+】掌控板入门教程01 “秀”出我创意

我们的好朋友麦乐佳即将举办一场派对&#xff0c;她要求每个参加派对的人都要佩戴一个可以彰显自己独特创意的装置。可以是会发光的帽子&#xff0c;可以是复古的电子表&#xff0c;还可以是其他有创意的作品。而现在&#xff0c;我们的手边刚好有一块掌控板&#xff0c;它自带…...

操作系统篇--八股文学习第十一天|进程调度算法你了解多少,进程间有哪些通信方式,解释一下进程同步和互斥,以及如何实现进程同步和互斥

进程调度算法你了解多少&#xff1f; 答&#xff1a; 先来先服务&#xff1a;按照请求的顺序进行调度。 这种调度方式简单&#xff0c;但是能导致较长作业阻塞较短作业。最短作业优先&#xff1a;非抢占式的调度算法&#xff0c;按估计运行时间最短的顺序进行调度。 但是如果…...

慢慢欣赏arm64内核启动6 primary_entry之el2_setup代码第三部分

分析代码 解析完虚拟化部分&#xff0c;我们继续分析启动过程中&#xff0c;对中断控制器的处理 #ifdef CONFIG_ARM_GIC_V3/* GICv3 system register access */mrs x0, id_aa64pfr0_el1ubfx x0, x0, #ID_AA64PFR0_GIC_SHIFT, #4cbz x0, 3fmrs_s x0, SYS_ICC_SRE_EL2orr x0, x…...

初谈Linux多线程--线程控制

文章目录 线程的概述理解线程Linux中的线程重新理解的进程Windows的线程线程的优点线程的缺点理解线程调度成本低 进程VS线程 线程控制创建线程等待线程线程函数传参线程的返回值新线程的返回值新线程返回值错误返回值为类对象 创建多线程线程的终止线程的分离pthread_detach 线…...

文件工具类 - FileUtils

Slf4j Component public class FileUtils {/*** 文件夹复制到指定的文件夹*/SneakyThrowspublic static void copyDir(File source, File target) {if (!target.exists()) {boolean mkdirs target.mkdirs();}if (source.isDirectory()) {File[] files source.listFiles();if …...

Kafka源码剖析-Producer基于内存缓存池分配ByteBuffer

文章目录 在将消息发送到内存缓中区之前做的准备工作发送消息前的准备工作代码示例源码分析1. **消息序列化**2. **元数据准备**3. **分区选择**4. **批处理准备**总结大致浏览一下源码中将消息写入内存缓冲的运行流程源码分析1. **消息序列化和创建记录批次**2. **确定分区**3…...

实习十九:学习笔记

上午 1、构建vue发行版本 [rootserver ~]# cd eleme_web/ [rootserver eleme_web]# npm run buid //项目未执行时运行该命令&#xff0c;创建发行版本 [rootserver eleme_web]# cd dist/ //dist中包含发行版本的所有文件 [rootserver dist]# ls css favicon.ico i…...

OrionX:革新GPU资源管理,助力AI开发团队高效运作

您的AI开发团队是否经常陷入这样的窘境&#xff1a; 人多卡少&#xff0c;GPU资源难以满足每个成员的需求&#xff1f; 当开发环境中需要变更GPU卡配置时&#xff0c;流程繁琐不堪&#xff0c;不得不关闭容器、重新配置再重启&#xff1f; 是否曾因GPU卡分配后未被充分利用而…...

RabbitMQ发送者重连、发送者确认

RabbitMQ发送者重连、发送者确认 一、发送者重连 spring:rabbitmq:connection-timeout: 1s #设置MQ的连接超时时间template:retry:enabled: true #开启超时重试机制initial-interval: 1000ms #失败后的初始等待时间multiplier: 1 #失败后下次的等待时长倍数&#xff0c;下次等…...

请转告HPC计算AI计算单位,选对存储事半功倍

U.2 NVMe全闪混合统一存储GS 5000U是Infortrend产品中一款高性能机型。得益于搭载强劲的第五代IntelXeon处理器&#xff0c;以及支持PCIe 5.0、NVMe-oF、100GbE等多种特点&#xff0c;GS 5000U单台块级性能可达50 GB/s的读、20 GB/s的写&#xff0c;以及1300K的IOPS&#xff1b…...

[GYCTF2020]Blacklist1

打开题目 判断注入类型&#xff0c;输入1试试 输入2 输入1 判断为字符型注入 堆叠查询2;show databases;# 然后来输入2; show tables;#来查看数据库的表 然后我们通过FlagHere表来查看列输入2;show columns from FlagHere;# 来查看列 、 重新构造payload&#xff1a;0;HAND…...

Blackcat V2.2付费会员制WordPress资源站主题

Blackcat-付费会员制WordPress资源站主题&#xff0c;该主题是基于简约实用的主题选项框架 Codestar Framework 进行开发的功能强大的付费会员制主题&#xff0c;该主题尤其适合用于搭建付费下载资源网站&#xff0c;比如素材站、软件站、视频教程站等付费资源下载网站。 集成…...

动手学强化学习 第 18 章 离线强化学习 训练代码

基于 https://github.com/boyu-ai/Hands-on-RL/blob/main/%E7%AC%AC18%E7%AB%A0-%E7%A6%BB%E7%BA%BF%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0.ipynb 理论 离线强化学习 修改了警告和报错 运行环境 Debian GNU/Linux 12 Python 3.9.19 torch 2.0.1 gym 0.26.2 运行代码 CQL.…...

Python笔试面试题AI答之面向对象常考知识点

Python面向对象面试题面试题覆盖了Python面向对象编程&#xff08;OOP&#xff09;的多个重要概念和技巧&#xff0c;包括元类&#xff08;Metaclass&#xff09;、自省&#xff08;Introspection&#xff09;、面向切面编程&#xff08;AOP&#xff09;和装饰器、重载&#xf…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)

macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 &#x1f37a; 最新版brew安装慢到怀疑人生&#xff1f;别怕&#xff0c;教你轻松起飞&#xff01; 最近Homebrew更新至最新版&#xff0c;每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

毫米波雷达基础理论(3D+4D)

3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

DBLP数据库是什么?

DBLP&#xff08;Digital Bibliography & Library Project&#xff09;Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高&#xff0c;数据库文献更新速度很快&#xff0c;很好地反映了国际计算机科学学术研…...