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

TensorFlow DAY3: 高阶 API(Keras,Estimator)(完)

TensorFlow 作为深度学习框架,当然是为了帮助我们更便捷地构建神经网络。所以,本次实验将会了解如何使用 TensorFlow 来构建神经网络,并学会 TensorFlow 构建神经网络的重要函数和方法。

知识点
  • Keras 顺序模型
  • Keras 函数模型
  • Keras 模型存储及推理
  • Estimator 高阶 API

Keras 本来是一个用 Python 编写的独立高阶神经网络 API,它能够以 TensorFlow,CNTK,或者 Theano 作为后端运行。目前,TensorFlow 已经吸纳 Keras,并组成了 tf.keras 模块 。官方介绍,tf.keras 和单独安装的 Keras 略有不同,但考虑到未来的发展趋势,实验以学习 tf.keras 为主。

                                        

通过查阅官方文档,你可以发现 tf.keras  下又包含 10 多个子模块,而这些子模块下又集成了大量的类和函数。由于 Keras 先前是独立发布的,实际上我们在仅使用 tf.keras 的情况下,就几乎能够满足深度神经网络搭建的全部需求。 

下面,我们对 Keras 进行快速上手介绍。Keras 的核心数据结构是 Model,一种组织网络层的方式。其中有两种模式,最简单且最常用的模型是 Sequential 顺序模型,它是由多个网络层线性堆叠的栈。对于更复杂的结构,可以使用 Keras 函数式 API,它允许构建任意的神经网络图。 

Keras 顺序模型

使用 Keras 创建一个 Sequential 顺序模型非常简单,只需要 1 行代码 tf.keras.models.Sequential()  就可以搞定。

import tensorflow as tfmodel = tf.keras.models.Sequential()  # 定义顺序模型
model

当然,上面这行代码肯定还不是一个神经网络模型,只有向其中添加不同结构的神经网络层,才能真正成为一个我们需要的神经网络模型。这里我们选择前面实验已经构建过的简单全连接神经网络。

                        

Keras 中的神经网络层全部位于 tf.keras.layers  下方。这里包含了各自经典神经网络所需的功能层,例如我们这里需要的全连接层 tf.keras.layers.Dense

Dense(units, activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)
  • units: 正整数,输出空间维度。
  • activation: 激活函数。若不指定,则不使用激活函数 (即线性激活:a(x) = x)。
  • use_bias: 布尔值,该层是否使用偏置项量。
  • kernel_initializerkernel 权值矩阵的初始化器。
  • bias_initializer: 偏置项量的初始化器。
  • kernel_regularizer: 运用到 kernel 权值矩阵的正则化函数。
  • bias_regularizer: 运用到偏置项的正则化函数。
  • activity_regularizer: 运用到层的输出的正则化函数。
  • kernel_constraint: 运用到 kernel 权值矩阵的约束函数。
  • bias_constraint: 运用到偏置项量的约束函数。

Dense 实现操作: output = activation(dot(input, kernel) + bias),其中 activation 是按逐个元素计算的激活函数,kernel 是由网络层创建的权值矩阵,以及 bias 是其创建的偏置项 (只在 use_bias 为 True 时才有用)。通过参数你就会发现,这是一个封装了很多功能的高阶 API。 

下面,我们就向上面定义好的顺序模型 model 中添加 2 个全连接层。

# 添加全连接层
model.add(tf.keras.layers.Dense(units=30, activation=tf.nn.relu))  # 输出 30,relu 激活
model.add(tf.keras.layers.Dense(units=10, activation=tf.nn.softmax))  # 输出 10,softmax 激活

你可以发现,一开始我们定义顺序模型就像是「打地基」,而只需要使用 add 就可以「盖楼房」了。上面的代码中,激活函数 tf.nn.relu 也可以用名称 'relu' 代替,即可写作 tf.keras.layers.Dense(units=30, activation='relu'),具体参考 官方文档。 

添加完神经网络层之后,就可以使用 model.compile  来编译顺序模型。这时,需要通过参数指定优化器,损失函数,以及评估方法。

# adam 优化器 + 交叉熵损失 + 准确度评估
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])

其中,参数可以使用如上所示的名称或者 TensorFlow 实例。如果使用实例的优化器和损失函数,需要从 TensorFlow 支持的  全部优化器列表 和  全部损失函数列表 中选择。如果使用名称,需要从 Keras 支持的  名称列表 中选择。 

特别注意的是,这里的损失函数是不能胡乱选的。你需要根据网络的输出形状和真实值的形状来决定。如果不匹配就会报错。由于实验示例网络最后通过了 tf.nn.softmax 激活,那么对于单个样本输入最终就会得到一个概率最大的整数类型的输出。此时就选择了 sparse_categorical_crossentropy 具有整数输出类型的交叉熵损失函数。随着实验后续深入,见的越多就会有使用经验了。 

PS:上面指的是你最终拿到的真实标签是one-hot还是说是整数值,这个sparse_categorical_crossentropy 最终也会把这个整数值转换成one-hot进行运算

接下来,我们定义数据,同样选择 DIGITS 数据集。

from sklearn.model_selection import train_test_split
from sklearn.datasets import load_digits
import numpy as np# 准备 DIGITS 数据
digits = load_digits()
X_train, X_test, y_train, y_test = train_test_split(digits.data, digits.target, test_size=0.2, random_state=1)X_train.shape, X_test.shape, y_train.shape, y_test.shape

这里无需像前面的实验对目标值进行独热编码,原因在于上面定义的网络最终输出本身就是样本类别整数。

定义完数据之后,使用 model.fit  就可以开始模型训练了。这个过程和使用 scikit-learn 训练模型一样直观。我们需要指定小批量 batch_size 大小,和全数据迭代次数 epochs 参数。

# 模型训练
model.fit(X_train, y_train, batch_size=64, epochs=5)

你可以看到每一个 Epoch 之后模型在训练数据上的损失和分类准确度。使用 model.evaluate 即可评估训练后模型在测试集上的损失和分类准确度。

# 模型评估
model.evaluate(X_test, y_test)

实际使用过程中,我们一般会直接将测试数据通过 validation_data 参数传入训练过程。那么,每一个 Epoch 之后都会同时输出在训练集和测试集上的分类评估结果。 

# 使用参数传入测试数据
model.fit(X_train, y_train, batch_size=64, epochs=5,validation_data=(X_test, y_test))

可以看到,区别于前面实验中较为复杂的模型定义过程,使用 Keras 提供的顺序模型只需要数行左右的代码即可完成。除此之外,你不需要初始化权重,编写前向计算图,设计 Mini Batch 机制,自定义评估方法和过程等。基本上把搭建神经网络中复杂的过程都省略了,只留下了直观的构建方法。这也就是 Keras 深受欢迎的原因,也是 TensorFlow 将 Keras 纳入的原因。

前面虽然我们仅使用了少数几个方法,但是你会发现每个方法涉及到的参数都非常多。这些参数可以帮助开发者在高阶 API 上进一步实现高度自定义过程。对于初学者而言,不要想一次性全部了解,随着后续对深度学习的逐渐深入,慢慢的都会熟悉起来。实际情况中,就算熟悉的开发者也不可能记得住每个 API 及参数,很多时候都是需要使用时才查阅官方文档。退一步讲,由于 TensorFlow API 变化更新的速度非常快,就算这次记住了,下次说不定还是需要查阅官方文档。 

Keras 函数模型

除了顺序模型,Keras 也提供函数式 API。和顺序模型最大的不同在于,函数模型可以通过多输入多输出的方式。并且所有的模型都是可调用的,就像层一样利用函数式模型的接口,我们可以很容易的重用已经训练好的模型。

下面,我们通过函数式 API 来重写上面的模型结构。

inputs = tf.keras.Input(shape=(64,))  # 输入层
x = tf.keras.layers.Dense(units=30, activation='relu')(inputs)  # 中间层
outputs = tf.keras.layers.Dense(units=10, activation='softmax')(x)  # 输出层# 函数式 API 需要指定输入和输出
model = tf.keras.Model(inputs=inputs, outputs=outputs)
model

模型编译和训练和顺序模型基本一致。

model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])model.fit(X_train, y_train, batch_size=64, epochs=20,validation_data=(X_test, y_test))

通过上面的示例,相信你已经看出了顺序模型和函数式模型的区别。函数式模型看起来更符合建模流出,有清晰的输入和输出,灵活性也更好一些。实际上对于二者,主要是看个人使用习惯,初学者可以根据自己的偏好自由选择。

Keras 模型存储及推理

使用 Keras 训练完成的模型可以非常方便地保存下来,保存模型的目的主要有 2 个:

  1. 对于较大的训练任务,保存模型可以方便后续恢复重新使用。
  2. 保存后的模型可以方便模型部署。

TensorFlow 模型一般包含 3 类要素,分别是:模型权重值、模型配置乃至优化器配置。 

如果只需要保存模型权重值,可以使用 tf.keras.Model.save_weights ,并指定存放路径。

model.save_weights('./weights/model')  # 保存检查点名称为 model,路径为 ./weights
!ls './weights/'  # 直接运行查看目录下文件

model.load_weights('./weights/model')  # 恢复检查点

默认情况下,该方法会以 TensorFlow 检查点文件格式  保存模型的权重。检查点文件是 TensorFlow 特有的模型权重保存方法,其默认会以每 10 分钟(600 秒)写入一个检查点,训练时间较短则只保存一个检查点。检查点默认情况下只保存 5 个,即模型训练过程中不同时间点的版本状态。

我们一般会在大型任务训练时设置检查点保存。这样做的好处在于一旦因为意外情况导致训练终止,TensorFlow 可以加载检查点状态,避免又需要从头开始训练。

如果我们需要模型推理,一般情况会使用 model.save 保存完整的模型,即包含模型权重值、模型配置乃至优化器配置等。例如,下面将模型存为 Keras HDF5 格式,其为 Keras 多后端实现的默认格式。

model.save('model.h5')  # 保存完整模型

接下来,可以使用 tf.keras.models.load_model 重载模型。

model_ = tf.keras.models.load_model('model.h5')  # 调用模型

model.summary() 可以用来查看 Keras 模型结构,包含神经网络层和参数等详细数据。

model_.summary()

然后,使用 predict 方法就可以完成模型推理了。

preds = model_.predict(X_test[:3])  # 预测前 3 个测试样本
preds

预测结果为神经网络通过 Softmax 激活后的输出值。所以我们通过 NumPy 找出每个样本输出最大概率及其对应的索引,其索引也就是最终的预测目标了。同样,可以输出测试数据真实标签进行对比。

np.argmax(preds, axis=1), np.max(preds, axis=1)  # 找出每个样本预测概率最大值索引及其概率
y_test[:3]  # 直接运行查看前 3 个测试样本真实标签

一般情况下,模型的预测是正确的。如果错误可以检查上方模型的评估情况,合理增大 Epoch 以提高模型准确度。

Estimator 高阶 API 

上面已经对使用 tf.keras 构建神经网络进行了学习。当然,随着后续学习的深入会逐步介绍更多用途的神经网络层,以及更丰富的用法。本小节中,我们会对 TensorFlow 另一个非常重要的组件 Estimator 进行介绍。

Estimator 是 TensorFlow 中的高阶 API,它可以将模型的训练、预测、评估、导出等操作封装在一起,构成一个 Estimator。TensorFlow 也提供了大量的预创建 Estimator ,例如线性回归,提升树分类器,深度神经网络分类器等。接下来,我们就利用 TensorFlow 提供的预创建的 tf.estimator.DNNClassifier  全连接深度神经网络来完成对示例数据的学习。

使用预创建的 Estimator 编写 TensorFlow 程序,大致需要执行下列几个步骤:

  1. 创建一个或多个输入函数。
  2. 定义模型的特征列。
  3. 实例化 Estimator,指定特征列和各种超参数。
  4. 在 Estimator 对象上调用一个或多个方法,传递适当的输入函数作为数据的来源。

下面,我们就按 4 个步骤来完成。首先,输入到 Estimator 的训练、评估和预测的数据都必须要通过创建输入函数来完成。

输入函数是返回 tf.data.Dataset  对象的函数,此对象会输出下列含有两个元素的元组:

  • features - Python 字典,其中:
    • 每个键都是特征的名称。
    • 每个值都是包含此特征所有值的数组。
  • label - 包含每个样本的标签值的数组。

所以下面我们将原来的 NumPy 数组转换为 Pandas 提供的 DataFrame,这样就可以方便地将数据转换成输入函数要求的 Python 字典类型。

import pandas as pd# NumPy 数组转换为 DataFrame,并将特征列名处理成字符串类型
X_train_ = pd.DataFrame(X_train, columns=[str(i) for i in range(64)])
y_train_ = pd.DataFrame(y_train, columns=['class'])  # 标签列名
X_test_ = pd.DataFrame(X_test, columns=[str(i) for i in range(64)])
y_test_ = pd.DataFrame(y_test, columns=['class'])

此时,如果你就可以直接将 DataFrame 处理成字典类型了,列名为键,数据为值。

dict(X_train_).keys()  # 运行使用 dict 将数据处理成输入函数要求的字典类型

我们直接开始定义数据输入函数 input_fntf.data.Dataset  对象是 TensorFlow 强烈推荐使用的数据管道。当数据为 Dataset 时,你就可以使用 TensorFlow 提供的一系列方法对数据进行变换,例如打乱采样,重复扩展,小批量输入等。

def input_fn(features, labels, batch_size):"""数据输入函数"""# 将数据转换为 Dataset 对象dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))# 将数据重复及处理成小批量dataset = dataset.repeat().batch(batch_size)return dataset

上面的代码中,tf.data.Dataset.from_tensor_slices 函数创建一个代表数组切片的 tf.data.Dataset。系统会在第一个维度内对该数组进行切片。然后 dataset 执行了 repeat 重复序列操作,这样做的目的是保证后续能迭代更多次,否则当数据一遍轮完之后训练就终止了。repeat() 代表无限扩展,即到我们设定的迭代次数。repeat(5) 则表示重复序列 5 次,样本数据变为原来的 5 倍。接着,我们使用了 batch 每次从数据中取出 batch_size 的小批量进行迭代。 

这样,创建数据输入函数就大功告成了。接下来,完成第二步:定义模型的特征列。

特征列是原始数据和 Estimator 之间的媒介,定义特征列就是告诉 Estimator 哪些是特征,每个特征的数据有什么特点。定义特征列并不是说指定几个字符串那样简单,我们需要利用 TensorFlow 提供的方法创建 Estimator 能够识别的特征列。

下面,我们将特征 DataFrame 的列名取出来,并使用 tf.feature_column.numeric_column  将其转换为特征列。该方法即告诉 Estimator 特征是 Numeric 数值类型。更多类型的特征列可以参考官方文档 。

feature_columns = []
for key in X_train_.keys():  # 取出 DataFrame 列名feature_columns.append(tf.feature_column.numeric_column(key=key))  # 创建数值特征列feature_columns[:3]  # 查看前 3 个特征列

完成第 2 步之后,第 3 步是:实例化 Estimator,指定特征列和各种超参数。这里使用 tf.estimator.DNNClassifier,需要传入特征列并定义隐含层神经元数量即目标值标签数量。

classifier = tf.estimator.DNNClassifier(# 特征列feature_columns=feature_columns,# 两个隐含层分别为 30 和 10 个神经元hidden_units=[30, 10],# 模型最终标签类别为 10n_classes=10)

紧接着,就可以在 Estimator 对象上调用一个或多个方法,传递适当的输入函数作为数据的来源。值得注意的是,这里将 input_fn 调用封装在 lambda 中以获取参数。

steps 参数告知方法在训练多少步后停止训练。steps 和先前的 Epoch 不一样,此时相当于取出 steps 个 batch_size 的数据用于训练。而整个训练过程等价于 steps * batch_size / 数据总量 个 Epoch。 所以,通过 steps 换算的 Epoch 可能不是整数,但这并不会影响到训练过程。

classifier.train(input_fn=lambda: input_fn(X_train_, y_train_, batch_size=64),steps=2000)

你可以看到上方训练执行的过程,权重会被自动存为检查点 .ckpt 文件。同时,后续的训练过程只有在 loss 更优时,检查点才会被覆盖。这样做的原因在于,后续的模型推理需要重载检查点权重,这样能保证存放的检查点性能状态最优。 

下面,我们使用测试数据对模型进行推理评估。此时,我们需要重新定义数据输入函数 evaluate_input_fn,原因在于之前定义的输入函数 input_fn 执行了 repeat() 操作,如果沿用就会导致推理无限持续下去。 

def evaluate_input_fn(features, labels, batch_size):"""评估数据输入函数"""# 将数据转换为 Dataset 对象dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))# 将仅处理成小批量dataset = dataset.batch(batch_size)return dataset

最终,使用 evaluate 评估模型,传入数据的过程和训练时相似。Estimator 会自动重载训练保存的检查点,并对测试数据进行推理和评估。

# 评估模型
eval_result = classifier.evaluate(input_fn=lambda: evaluate_input_fn(X_test_, y_test_, batch_size=64))print('最终评估准确度:{:.3f}'.format(eval_result['accuracy']))

最终,我们就可以得到测试结果。除了大量的预创建 Estimator,你也可以根据自己的需要自定义 Estimator,这部分内容可以直接阅读  官方文档相关章节。对于 Estimator,TensorFlow 官方推荐的工作流程如下:

  1. 假设存在合适的预创建的 Estimator,使用它构建第一个模型并使用其结果确定基准。
  2. 使用此预创建的 Estimator 构建和测试整体管道,包括数据的完整性和可靠性。
  3. 如果存在其他合适的预创建的 Estimator,则运行实验来确定哪个预创建的 Estimator 效果最好。
  4. 可以通过构建自定义 Estimator 进一步改进模型。

神经网络搭建方法小结 

通过几个实验的学习,目前我们掌握了 3 种搭建神经网络的方法:

  • 利用 tf.nn 模块提供的各种神经网络组件和函数。
  • 利用 tf.keras 模块提供的各种高阶神经网络层。
  • 利用 tf.estimator 提供的高阶预创建或自定义封装模型。

大多情况下,使用这三种方法都可以实现我们的想法。不过,这里有一些使用经验供参考。

如果需要实现的网络自定义程度较高,有很多自己的想法且并没有合适的高阶 API 层供调用,那么首选肯定是 tf.nntf.nn 功能强大,但你需要自行定义训练迭代过程,且大多数过程都需要利用 TensorFlow 一系列低阶 API 完成。tf.keras 模块主要面向于实现包含标准化层的神经网络,例如后面会学习的经典卷积神经网络结构等。API 使用方便,简洁明了。

tf.estimator 本身在 tf.keras 之上构建而成,Keras 模型也可以通过创建 Estimator 进行训练 。Estimator 简化了在模型开发者之间共享实现的过程,其可以在本地主机上或分布式多服务器环境中运行基于 Estimator 的模型,而无需更改模型。但 Estimator 的使用可能需要对 TensorFlow 足够熟悉之后才能得心应手。

实验总结

本次实验重点了解了 TensorFlow 中的 Keras 和 Estimator 的使用,并结合我们前面的例子进行了模型重写。Keras 是非常常用的 API,随着我们面对的模型复杂程度上升,高阶 API 的优势也会进一步显现。

相关文章:

TensorFlow DAY3: 高阶 API(Keras,Estimator)(完)

TensorFlow 作为深度学习框架,当然是为了帮助我们更便捷地构建神经网络。所以,本次实验将会了解如何使用 TensorFlow 来构建神经网络,并学会 TensorFlow 构建神经网络的重要函数和方法。 知识点 Keras 顺序模型Keras 函数模型Keras 模型存储…...

复健第二天之[MoeCTF 2022]baby_file

打开题目在线环境可以看到: 感觉要用伪协议去求,但是我们并不知道flag的位置,这里我选择用dirsearch去扫一下: 最像的应该就是flag.php了 于是就构建payload: **?filephp://filter/convert.base64-encode/resource…...

【QT用户登录与界面跳转】

【QT用户登录与界面跳转】 1.前言2. 项目设置3.设计登录界面3.1 login.pro参数3.2 界面设置3.2.1 登录界面3.2.2 串口主界面 4. 实现登录逻辑5.串口界面6.测试功能7.总结 1.前言 在Qt应用程序开发中,实现用户登录及界面跳转功能是构建交互式应用的重要步骤之一。下…...

【docker踩坑记录】

docker踩坑记录 踩坑记录(持续更新中.......)docker images 权限问题 踩坑记录(持续更新中…) docker images 权限问题 permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Head "http://%2Fvar%2Frun%2Fdocker.s…...

【Azure 架构师学习笔记】- Azure Function (2) --实操1

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Function 】系列。 接上文【Azure 架构师学习笔记】- Azure Function (1) --环境搭建和背景介绍 前言 上一文介绍了环境搭建,接下来就在本地环境下使用一下。 环境准备 这里我下载了最新的VS studio&…...

豆包MarsCode:构造特定数组的逆序拼接

问题描述 思路分析 1. 数组的组成: 我们要根据 i 的不同值拼接出不同长度的子数组。对于每个 i 从 1 到 n,我们要把数字从 n 逆序到 i 拼接成一个子数组。 例如,当 i 1 时,拼接 [n, n-1, ..., 1]。当 i 2 时,拼接 …...

14-美妆数据分析

前言 美妆数据分析可以帮助企业更好地理解市场趋势、客户偏好和产品表现 import pandas as pd import numpy as np 一、数据清洗 data pd.read_csv(rC:\Users\B\Desktop\美妆数据.csv,encodinggbk) data.head()data.info()data data.drop_duplicates(inplaceFalse) data.r…...

新阿里云买服务器配置需手动配置80端口

新买阿里云服务器需手动配置80,端口才可以访问nginx CentOS系统 安装nginx 1. 安装 Nginx yum install nginx 2. 启动 Nginx 服务 systemctl start nginx 3. 修改默认网页 cd /usr/share/nginx/ echo "666" >index.html cat index.html 访问ngin最后…...

Mysql--实战篇--连接泄漏问题(什么是连接泄漏,未关闭SqlSession,长事务处理,连接池管理等)

1、什么是连接泄漏(Connection Leak)? 连接泄漏是指应用程序未能正确关闭数据库连接,导致连接池中的可用连接逐渐减少,最终耗尽所有连接。连接泄漏可能会导致新的请求无法获得连接,进而引发服务中断。 连…...

【ESP32】ESP-IDF开发 | WiFi开发 | AP模式 + 基站连接例程

1. 简介 前面一篇讲了WiFi的基站模式,演示了怎么编程连接AP,所以这一篇讲一讲AP模式,ESP32作AP,让其他的设备连接自己。 1.1 DHCP 这里需要补充一个知识点——DHCP服务器。当基站连接一个AP时,会被分配一个IP&#xf…...

Ubuntu升级Linux内核教程

本文作者CVE-柠檬i: CVE-柠檬i-CSDN博客 本文使用的方法是dpkg安装,目前版本为5.4.0-204,要升级成5.8.5版本 下载 下载网站:https://kernel.ubuntu.com/mainline/ 在该网站下载deb包,选择自己想要升级的版本,这里是5…...

关于AWS网络架构的思考

目录: AWS概述 EMR Serverless AWS VPC及其网络 关于AWS网络架构的思考 在AWS K8S中部署的业务,有不同的流量路径。 流量进入 客户端请求 普通的客户端流量流向从前到后是: 客户端公司网关(endpoint)业务的Endpoint ServiceLoad Balancers(监听80和…...

Pandas库的常用内容归纳

Pandas 是一个强大的 Python 数据分析库,提供了大量用于数据处理和分析的功能。以下是一些 Pandas 库中常用的功能: 数据创建和操作 Series 和 DataFrame:创建一维的 Series 和二维的 DataFrame 对象。数据导入:从 CSV、Excel、…...

【错误解决方案记录】spine3.8.75导出的数据使用unity-spine3.8插件解析失败报错的解决方案

报错信息 Exception: Unsupported skeleton data, please export with a newer version of Spine. Spine.SkeletonBinary.ReadSkeletonData (System.IO.Stream file) (at Assets/Spine/Runtime/spine-csharp/SkeletonBinary.cs:132) Spine.Unity.Editor.AssetUtility.AddRequi…...

Python与PyTorch的浅拷贝与深拷贝

1.Python赋值操作的原理 在python中,x something, 这样的赋值操作,准确的理解是:给存储something建立一个索引x (即存储地址), x通过访问something的存储内容,获得something的值。 在下面代码中&#xff…...

【unity进阶篇】弧度、角度和三角函数(Mathf),并实现类似蛇的运动

考虑到每个人基础可能不一样,且并不是所有人都有同时做2D、3D开发的需求,所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】:主要讲解C#的基础语法,包括变量、数据类型、运算符、…...

【分类】【损失函数】处理类别不平衡:CEFL 和 CEFL2 损失函数的实现与应用

引言 在深度学习中的分类问题中,类别不平衡问题是常见的挑战之一。尤其在面部表情分类任务中,不同表情类别的样本数量可能差异较大,比如“开心”表情的样本远远多于“生气”表情。面对这种情况,普通的交叉熵损失函数容易导致模型…...

支持selenium的chrome driver更新到132.0.6834.83

最近chrome释放新版本:132.0.6834.83 如果运行selenium自动化测试出现以下问题,是需要升级chromedriver才可以解决的。 selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only su…...

IO模型与NIO基础二

抽象基类之二 FilterInputStream FilterInputStream 的作用是用来“封装其它的输入流,并为它们提供额外的功能”。 它的常用的子类有BufferedInputStream和DataInputStream。 (1) BufferedInputStream的作用就是为“输入流提供缓冲功能,以及mark()和res…...

什么是FPGA开发?

FPGA(Field-Programmable Gate Array),即现场可编程门阵列,是一种通过编程方式实现特定功能的集成电路。与传统的ASIC(专用集成电路)相比,FPGA具有灵活性高、开发周期短、成本相对较低等优势&am…...

寻找川味:成都九尺板鸭

寻找川味:成都九尺板鸭 在四川这片美食的天堂里,隐藏着无数令人垂涎的传统名吃。其中,成都九尺板鸭以其悠久的历史、独特的制作工艺和令人难以抗拒的美味,成为了许多食客心中不可错过的地道川味。 历史渊源 九尺板鸭,顾名思义,因主产于四川省成都市彭州市九尺镇而得名。早在5…...

Object常用的方法及开发中的使用场景

在前端开发中,Object 对象提供了许多常用的方法,这些方法帮助我们操作对象的属性和结构。以下是常用的 Object 方法及其功能简要说明: 对象常用的方法 1. 创建对象 Object.create(proto[, propertiesObject]) 创建一个具有指定原型对象和属性…...

ElasticSearch上

安装ElasticSearch Lucene:Java语言的搜索引擎类库,易扩展;高性能(基于倒排索引)Elasticsearch基于Lucene,支持分布式,可水平扩展;提供Restful接口,可被任何语言调用Ela…...

基于SpringCloud的广告系统设计与实现(二)

一、common公共模块 1.common的作用 通用的代码、配置不应该散落在各个业务模块中,不利于维护与更新 一个大的系统,响应对象需要统一外层格式 各种业务设计与实现,可能会抛出各种各样的异常,异常信息的收集也应该做到统一 2.统…...

2011年西部数学奥林匹克的几何题

2011G1 证明: 显然, O O O, I I I, F F F 共线, E I / / M O EI//MO EI//MO, △ E I F ∼ △ M O F \triangle EIF \sim \triangle MOF △EIF∼△MOF. 进而 E F / M F r 1 / r 2 EF/MFr_1/r_2 EF/MFr1​/r2​. ( r 1 (r_1 (r1​ 为圆 I I I 的半径, r 2 r_2 r2​ 为…...

(一)afsim第三方库编译

注意:防止奇怪的问题,源码编译的路径最好不要有中文,请先检查各文件夹名 AFSIM版本 Version: 2.9 Plugin API Version: 11 软件环境 操作系统: Kylin V10 SP1 项目构建工具: cmake-3.26.0-linux-aarch6…...

boss直聘 __zp_stoken__ 分析

声明: 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 逆向过程 py代码 import execjs imp…...

python matplotlib绘图,显示和保存没有标题栏和菜单栏的图像

目录 1. 使用plt.savefig保存无边框图形 2. 显示在屏幕上,并且去掉窗口的标题栏和工具栏 3. 通过配置 matplotlib 的 backend 和使用 Tkinter(或其他图形库) 方法 1:使用 TkAgg 后端,并禁用窗口的工具栏和标题栏 …...

AI-Talk开发板之替换唤醒词

一、说明 聆思提供的Demo唤醒词默认为"小美,小美",V2.4及之后的SDK支持替换唤醒词,聆思提供了在线工具生成唤醒词固件。 工具:tool.listenai.com/audio-custom/products/ 官方博客教程:实操给桌面AI语音助理&#xff…...

C#实现字符串反转的4种方法

见过不少人、经过不少事、也吃过不少苦,感悟世事无常、人心多变,靠着回忆将往事串珠成链,聊聊感情、谈谈发展,我慢慢写、你一点一点看...... 1、string.Reverse 方法 string content "Hello World";string reverseStri…...

【MySQL索引:B+树与页的深度解析】

文章目录 MySQL索引:B树与页的深度解析1. 索引使用的数据结构——B树1.1 B树介绍1.2 B树的特点1.3 B树和B树的对比 2. MySQL中的页2.1 页的介绍2.2 页主体2.3 页目录2.4 B树在MySQL索引中的应用 MySQL索引:B树与页的深度解析 在MySQL数据库中&#xff0…...

在 macOS 上,用命令行连接 MySQL(/usr/local/mysql/bin/mysql -u root -p)

根据你提供的文件内容,MySQL 的安装路径是 /usr/local/mysql。要直接使用 mysql 命令,你需要找到 mysql 可执行文件的路径。 在 macOS 上,mysql 客户端通常位于 MySQL 安装目录的 bin 子目录中。因此,完整的路径应该是&#xff1…...

深入HDFS——数据上传源码

引入 就如RPC篇章里提到的观点一样,任何一种能广为传播的技术,都是通过抽象和封装的思想,屏蔽底层底层复杂实现,提供简单且强大的工具,来降低使用门槛的。 HDFS的风靡自然也是如此。 通过前面深入了NameNode和DataN…...

归并排序算法

归并排序 1算法介绍 和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间。归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用…...

优雅解决webview_flutter不支持安卓选择图片视频文件问题

这个问题,网上一搜索,就是要去修改别人写好的插件。 搞Flutter开发,尽量不要去修改别人的插件 ,特别是像 webview_flutter 这种比较大的官方插件。 相信我,你拿捏不了它。 主要问题就是: webview_flutter…...

Linux UDP 编程详解

一、引言 在网络编程领域,UDP(User Datagram Protocol,用户数据报协议)作为一种轻量级的传输层协议,具有独特的优势和适用场景。与 TCP(Transmission Control Protocol,传输控制协议&#xff0…...

UllnnovationHub,一个开源的WPF控件库

目录 UllnnovationHub1.项目概述2.开发环境3.使用方法4.项目简介1.WPF原生控件1.Button2.GroupBox3.TabControl4.RadioButton5.SwitchButton6.TextBox7.PasswordBox8.CheckBox9.DateTimePicker10.Expander11.Card12.ListBox13.Treeview14.Combox15.Separator16.ListView17.Data…...

[Python学习日记-78] 基于 TCP 的 socket 开发项目 —— 模拟 SSH 远程执行命令

[Python学习日记-78] 基于 TCP 的 socket 开发项目 —— 模拟 SSH 远程执行命令 简介 项目分析 如何执行系统命令并拿到结果 代码实现 简介 在Python学习日记-77中我们介绍了 socket 基于 TCP 和基于 UDP 的套接字,还实现了服务器端和客户端的通信,本…...

css3过渡总结

一、过渡的定义与作用 CSS3 过渡(Transitions)允许 CSS 属性在一定的时间区间内平滑地过渡,从一个值转变为另一个值。它能够让网页元素的状态变化更加自然、流畅,给用户带来更好的视觉体验。例如,当一个元素从隐藏状态…...

生产环境中常用的设计模式

生产环境中常用的设计模式 设计模式目的使用场景示例单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点- 日志记录器- 配置管理器工厂方法模式定义一个创建对象的接口,让子类决定实例化哪个类- 各种工厂类(如视频游戏工厂模式创…...

【STM32-学习笔记-4-】PWM、输入捕获(PWMI)

文章目录 1、PWMPWM配置 2、输入捕获配置3、编码器 1、PWM PWM配置 配置时基单元配置输出比较单元配置输出PWM波的端口 #include "stm32f10x.h" // Device headervoid PWM_Init(void) { //**配置输出PWM波的端口**********************************…...

游戏行业销售数据分析可视化

完整源码项目包获取→点击文章末尾名片! 🌟分析: 可看出最近五年用户最喜爱的游戏类型依然还是Action-动作类(当然市场发行的也很多) Sports-运动类和Shooter-射击类顺序互换,但我估计现在大环境局势紧张可以会推动射击…...

微服务网关,如何选择?

什么是API网关 API网关(API Gateway)是微服务架构中的一个关键组件,它充当了客户端与后端服务之间的中间层。其主要功能包括请求路由、协议转换、负载均衡、安全认证、限流熔断等。通过API网关,客户端无需直接与多个微服务交互&a…...

Java开发提速秘籍:巧用Apache Commons Lang工具库

一、Java 开发效率之困 在当今数字化时代,Java 作为一门广泛应用的编程语言,在各类软件开发项目中占据着举足轻重的地位。无论是大型企业级应用、互联网平台,还是移动应用后端,都能看到 Java 的身影。然而,Java 开发者…...

多用户商城系统源码哪家好用?怎么选?

想拥有属于自己的多用户商城系统,但回头一看自己又是个技术小白,看着网上眼花缭乱的b2b2c商城系统,更是不知道如何选起?下面给大家分享一条较为成熟的选择思路,以作参考。 1、从需求上决定系统方向 企业在选型b2b2c商…...

聊聊如何实现Android 放大镜效果

一、前言 很久没有更新Android 原生技术内容了,前些年一直在做跨端方向开发,最近换工作用重新回到原生技术,又回到了熟悉但有些生疏的环境,真是感慨万分。 近期也是因为准备做地图交互相关的需求,功能非常复杂&#x…...

NVIDIA视频编解码

开源了两个项目:英伟达显卡视频编解码、jetson视频编解码。都是基于官方SDK进行的封装,由于官方自带的demo晦涩难懂并且每块都是独立的,我对SDK进行二次封装并形成了一套较为完整的视频编解码流程,调用简单,有完整的测…...

Mysql事务隔离级

什么是事务的隔离级别 数据库事务的隔离级别是指事务在并发执行时,如何控制事务之间相互影响的程度。它决定了多个事务并发执行时,事务中的操作对其他事务的可见性,进而影响数据的一致性和并发性。 为什么会有隔离级别的概念? …...

K210视觉识别模块

K210视觉识别模块是一款功能强大的AI视觉模块,以下是对其的详细介绍: 一、核心特性 强大的视觉识别功能:K210视觉识别模块支持多种视觉功能,包括但不限于人脸识别、口罩识别、条形码和二维码识别、特征检测、数字识别、颜色识别…...

springboot使用websocket

文章目录 一、概述1、简介 二、 使用1、引包2、配置处理器3、前端测试 一、概述 1、简介 简介略,附上官方文档,spring5和spring6的官方文档内容大致是一样的: https://docs.spring.io/spring-framework/docs/5.2.25.RELEASE/spring-framewo…...