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

政安晨:示例演绎TensorFlow的官方指南(一){基础知识}

为什么要示例演绎?

既然有了官方指南,咱们在官方指南上看看就可以了,为什么还要写示例演绎的文章呢?

其实对于初步了解TensorFlow的小伙伴们而言,示例演绎才是最重要的。

官方文档已经假定了您已经具备了相当合适的基础知识以及工作/学习环境,而这两点恰恰是很多小伙伴们的差异所在。

作者政安晨的工作生涯涉猎很广泛:从半导体芯片设计到硬件与射频通信电路开发,再从汇编语言的片上系统开发,C语言的Linux系统及其它嵌入式系统开发,中间件和应用开发,以及基于Python的数据抓取及分析业务开发(Python Web开发),还有go和nodejs的云平台产品开发,也包括图形编程、Arduino、智能硬件、传感器物联网、游戏产品、智能算法等等。

(有小伙伴可能会问了:你怎么可以做这么多东西,能精通得了吗?其实这里面有些根本逻辑是一直不会变的,每个人都有自己的内核,就像系统一样,内核要逐步加强而不能散乱,这样在职业技能的应用上才能千姿百态,向着一法通乃至万法通的状态探索。希望小伙伴们都能找到自己的内核。这个以后有机会给大家分享。)

顺着上面说,由此,老晨对官方文档的演绎不会只停留在单一维度上,在帮助大家踩坑的同时,也让大家看到直观地执行,希望这些文章成为大家的蹋脚石,让小伙伴们踩着我的理解继续前进!呵呵。

好,咱们开始!

Eager Execution

TensorFlow 的 Eager Execution 是一种命令式编程环境,可立即评估运算,无需构建计算图:运算会返回具体的值,而非构建供稍后运行的计算图。这样能使您轻松入门 TensorFlow 并调试模型,同时也减少了样板代码。要跟随本指南进行学习,请在交互式 python 解释器中运行以下代码示例。

Eager Execution 是用于研究和实验的灵活机器学习平台,具备以下特性:

  • 直观的界面 - 自然地组织代码结构并使用 Python 数据结构。快速迭代小模型和小数据。
  • 更方便的调试功能 - 直接调用运算以检查正在运行的模型并测试更改。使用标准 Python 调试工具立即报告错误。
  • 自然的控制流 - 使用 Python 而非计算图控制流,简化了动态模型的规范。

Eager Execution 支持大部分 TensorFlow 运算和 GPU 加速。

官方有个注释:

{注:启用 Eager Execution 后可能会增加某些模型的开销。我们正在持续改进其性能,如果您遇到问题,请提交错误报告并分享您的基准。}


老晨

与传统的TensorFlow方式不同,Eager Execution不需要显式地创建图,而是将操作应用于具体的张量数据并立即返回结果。

Eager Execution的工作原理如下:

  1. 张量表示:使用Eager Execution时,张量数据以普通的多维数组(numpy数组)的形式表示。
  2. 自动微分:Eager Execution支持自动计算梯度,使得在模型训练过程中能够方便地进行梯度下降等优化操作。
  3. 操作执行:在Eager Execution模式下,操作会立即执行并返回结果。这样可以方便地进行调试和验证。
  4. 动态模型构建:通过使用Python控制流语句,可以动态地构建模型,灵活地定义各种复杂的模型结构。

Eager Execution的主要优势是实时性和简洁性。它减少了构建静态计算图的复杂性,使得模型开发和调试过程更加直观和高效。在研究和探索新的模型架构时,Eager Execution可以帮助快速迭代和实验,而不需要考虑图构建的复杂性。同时,Eager Execution与TensorFlow的其他功能(如TensorBoard可视化和分布式训练)也可以无缝集成使用。


设置和基本用法

在这篇演绎中,我是基于本地环境运行TensorFLow的(CPU版本),对于这样指南性质的示例来说,足够了。

我照例打开了Jupyter Notebook,并加载了TensorFlow的虚拟环境,不清楚的小伙伴看我机器学习笔记里的文章:

政安晨的机器学习笔记——跟着演练快速理解TensorFlow(适合新手入门)icon-default.png?t=N7T8https://blog.csdn.net/snowdenkeke/article/details/135950931

import osimport tensorflow as tfimport cProfile

在 Tensorflow 2.0 中,默认启用 Eager Execution。

tf.executing_eagerly()

老晨执行:

现在您可以运行 TensorFlow 运算,结果将立即返回:

x = [[2.]]
m = tf.matmul(x, x)
print("hello, {}".format(m))

老晨执行:

启用 Eager Execution 会改变 TensorFlow 运算的行为方式 - 现在它们会立即评估并将值返回给 Python。tf.Tensor 对象会引用具体值,而非指向计算图中节点的符号句柄。由于无需构建计算图并稍后在会话中运行,可以轻松使用 print() 或调试程序检查结果。评估、输出和检查张量值不会中断计算梯度的流程。

Eager Execution 可以很好地配合 NumPy 使用。NumPy 运算接受 tf.Tensor 参数。TensorFlow tf.math 运算会将 Python 对象和 NumPy 数组转换为 tf.Tensor 对象。tf.Tensor.numpy 方法会以 NumPy ndarray 的形式返回该对象的值。

a = tf.constant([[1, 2],[3, 4]])
print(a)

老晨执行:


老晨

这个例子定义了一个二阶张量(也称二维张量),它的形状是(2, 2),类型是32位整型。

咱们人类的大脑其实更容易理解具象的东西,婴幼儿时期主要是具象思维,后来慢慢长大,逐步有了抽象思维(逻辑、推理等等)能力。所以在机器学习的领域中,您看到的很多现象的背后隐含方式都是要把抽象的东西转换成具象的表达,比如我们这里说的张量和形状。其实这没有什么好神秘的,大家不要被各种技术词儿给吓到了,技术词儿也是一些人说出来给另一些人听的(也包括我,呵呵)。

官方指南中接下来就是用张量做个运算。


# Broadcasting support
b = tf.add(a, 1)
print(b)

老晨执行:


老晨

小伙伴们仔细观察,张量b是在a张量的基础上各元素加1得来的。


# Operator overloading is supported
print(a * b)

老晨执行:


老晨

张量的乘法小伙伴们学过离散数学的就会清楚一点,这个就是矩阵乘法,因为a和b都是二阶张量,所以,张量a乘以张量b,就是张量a中对应位置与张量b中对应位置相乘,得出的新张量就是您看到的[[2 6] [12 20]],形状当然还是(2,2)。

接下来,官方指南中又演示了一些运算例子(基于NumPy库):


# Use NumPy values
import numpy as npc = np.multiply(a, b)
print(c)
# Obtain numpy value from a tensor:
print(a.numpy())
# => [[1 2]
#     [3 4]]

老晨执行:

动态控制流

Eager Execution 的一个主要优势是,在执行模型时,主机语言的所有功能均可用。因此,编写下面这类(FIZZBUZZ)的代码会很容易:

def fizzbuzz(max_num):counter = tf.constant(0)max_num = tf.convert_to_tensor(max_num)for num in range(1, max_num.numpy()+1):num = tf.constant(num)if int(num % 3) == 0 and int(num % 5) == 0:print('FizzBuzz')elif int(num % 3) == 0:print('Fizz')elif int(num % 5) == 0:print('Buzz')else:print(num.numpy())counter += 1
fizzbuzz(15)

老晨执行(定义函数,传参执行):

这段代码具有依赖于张量值的条件语句并会在运行时输出这些值。

Eager 训练

计算梯度

自动微分在对实现机器学习算法(例如用于训练神经网络的反向传播)十分有用。在 Eager Execution 期间,请使用 tf.GradientTape 跟踪运算以便稍后计算梯度。

您可以在 Eager Execution 中使用 tf.GradientTape 来训练和/或计算梯度。这对复杂的训练循环特别有用。

由于在每次调用期间都可能进行不同运算,所有前向传递的运算都会记录到“条带”中。要计算梯度,请反向播放条带,然后丢弃。特定 tf.GradientTape 只能计算一个梯度;后续调用会引发运行时错误。


政安晨:先了解两个术语

自动微分(Automatic Differentiation)是一种计算导数的方法,它在机器学习中起着重要的作用。在机器学习中,我们经常需要计算模型参数对于损失函数的梯度,以便使用梯度下降等优化算法来更新参数。

传统的数值微分方法往往需要使用数值近似的方式来计算导数,这样会引入舍入误差,并且计算效率较低。自动微分通过利用计算图的方式,可以有效地计算出精确的导数值,而且计算效率较高。

具体而言,自动微分通过将复杂的计算过程拆解为一系列基本的运算操作,然后利用链式法则计算相应的导数,从而得到每个操作的导数值。这种方式可以避免传统数值微分方法中存在的误差累积问题,并且可以高效地计算出所有参数的导数。

在机器学习中,自动微分被广泛应用于各种模型的训练过程中,包括神经网络、支持向量机、决策树等。通过自动微分,我们可以方便地计算出模型参数对于损失函数的梯度,并根据梯度来更新参数,从而提高模型的性能和准确度。

总之,自动微分是机器学习中计算导数的一种高效而准确的方法,它在模型训练和参数优化中起着重要的作用。

反向传播(backpropagation)是一种机器学习中用于训练神经网络的算法。它通过计算损失函数对网络中每个参数的梯度来更新参数的值,从而使网络的输出接近于预期的目标。

具体来说,反向传播通过两个步骤来计算梯度。首先,它根据网络的输入和当前参数的值来计算网络的输出。然后,它根据损失函数来计算输出与目标值之间的差异,并将误差通过网络向后传播。在这个过程中,反向传播通过链式法则计算每个参数对于损失函数的梯度。最后,使用计算出的梯度来更新参数的值,以降低损失函数的值。

反向传播具有以下几个重要的特点和优势:

  1. 反向传播是一种自动化的方法,可以直接计算网络中每个参数对于整个网络的输出的影响,而不需要手动推导导数。
  2. 反向传播可以高效地计算网络中大量参数的梯度,使得神经网络的训练更加快速和高效。
  3. 反向传播可以用于训练深度神经网络,使得神经网络可以学习更复杂、更抽象的特征和模式。

总之,反向传播在机器学习中扮演着重要的角色,为神经网络的训练提供了一种高效而自动化的方法,使得神经网络可以学习和逼近复杂的函数关系。


w = tf.Variable([[1.0]])
with tf.GradientTape() as tape:loss = w * wgrad = tape.gradient(loss, w)
print(grad)  # => tf.Tensor([[ 2.]], shape=(1, 1), dtype=float32)

老晨执行:

训练模型

以下示例创建了一个多层模型,该模型会对标准 MNIST 手写数字进行分类(政安晨:我有篇文章专门讲这个手写数字的数据集,是美国80年代训练的,在机器学习领域里经常用)。

政安晨的机器学习笔记——基于Anaconda安装TensorFlow并尝试一个神经网络小实例icon-default.png?t=N7T8https://blog.csdn.net/snowdenkeke/article/details/135841281好,我们接着下面的示例说,该示例演示了在 Eager Execution 环境中构建可训练计算图的优化器和层 API。

# Fetch and format the mnist data
(mnist_images, mnist_labels), _ = tf.keras.datasets.mnist.load_data()dataset = tf.data.Dataset.from_tensor_slices((tf.cast(mnist_images[...,tf.newaxis]/255, tf.float32),tf.cast(mnist_labels,tf.int64)))
dataset = dataset.shuffle(1000).batch(32)
# Build the model
mnist_model = tf.keras.Sequential([tf.keras.layers.Conv2D(16,[3,3], activation='relu',input_shape=(None, None, 1)),tf.keras.layers.Conv2D(16,[3,3], activation='relu'),tf.keras.layers.GlobalAveragePooling2D(),tf.keras.layers.Dense(10)
])

即使没有训练,也可以在 Eager Execution 中调用模型并检查输出:

for images,labels in dataset.take(1):print("Logits: ", mnist_model(images[0:1]).numpy())

政安晨执行:

虽然 Keras 模型有内置训练循环(使用 fit 方法),但有时您需要进行更多自定义。下面是一个使用 Eager Execution 实现训练循环的示例:

optimizer = tf.keras.optimizers.Adam()
loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)loss_history = []

注:请在 tf.debugging 中使用断言函数检查条件是否成立。这在 Eager Execution 和计算图执行中均有效。

def train_step(images, labels):with tf.GradientTape() as tape:logits = mnist_model(images, training=True)# Add asserts to check the shape of the output.tf.debugging.assert_equal(logits.shape, (32, 10))loss_value = loss_object(labels, logits)loss_history.append(loss_value.numpy().mean())grads = tape.gradient(loss_value, mnist_model.trainable_variables)optimizer.apply_gradients(zip(grads, mnist_model.trainable_variables))
def train(epochs):for epoch in range(epochs):for (batch, (images, labels)) in enumerate(dataset):train_step(images, labels)print ('Epoch {} finished'.format(epoch))
train(epochs = 3)

政安晨:有时候您执行Jupyter单元格的时候,可能会遇到执行后没有反应,不要慌,重启内核!

应该是您执行某段代码的时候让内核异常而部分不响应。

其实,我在演绎到这里的时候,已经发现我的CPU版内核(TensorFlow)开始出现不稳定的情况,所以,我切换到在线Colab继续为大家演绎。

政安晨执行:

import matplotlib.pyplot as pltplt.plot(loss_history)
plt.xlabel('Batch #')
plt.ylabel('Loss [entropy]')

图表显示:

变量和优化器

tf.Variable 对象会存储在训练期间访问的可变、类似于 tf.Tensor 的值,以更简单地实现自动微分。

变量的集合及其运算方法可以封装到层或模型中。有关详细信息,请参阅自定义 Keras 层和模型。层和模型之间的主要区别在于模型添加了如下方法:Model.fit、Model.evaluate 和 Model.save。

例如,上面的自动微分示例可以改写为:

class Linear(tf.keras.Model):def __init__(self):super(Linear, self).__init__()self.W = tf.Variable(5., name='weight')self.B = tf.Variable(10., name='bias')def call(self, inputs):return inputs * self.W + self.B
# A toy dataset of points around 3 * x + 2
NUM_EXAMPLES = 2000
training_inputs = tf.random.normal([NUM_EXAMPLES])
noise = tf.random.normal([NUM_EXAMPLES])
training_outputs = training_inputs * 3 + 2 + noise# The loss function to be optimized
def loss(model, inputs, targets):error = model(inputs) - targetsreturn tf.reduce_mean(tf.square(error))def grad(model, inputs, targets):with tf.GradientTape() as tape:loss_value = loss(model, inputs, targets)return tape.gradient(loss_value, [model.W, model.B])

下一步:

  1. 创建模型。
  2. 损失函数对模型参数的导数。
  3. 基于导数的变量更新策略。
model = Linear()
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)print("Initial loss: {:.3f}".format(loss(model, training_inputs, training_outputs)))steps = 300
for i in range(steps):grads = grad(model, training_inputs, training_outputs)optimizer.apply_gradients(zip(grads, [model.W, model.B]))if i % 20 == 0:print("Loss at step {:03d}: {:.3f}".format(i, loss(model, training_inputs, training_outputs)))

政安晨执行:

print("Final loss: {:.3f}".format(loss(model, training_inputs, training_outputs)))
print("W = {}, B = {}".format(model.W.numpy(), model.B.numpy()))

政安晨执行:

注:变量将一直存在,直至删除对 Python 对象的最后一个引用,并删除该变量。

基于对象的保存

tf.keras.Model 包括一个方便的 save_weights 方法,您可以通过该方法轻松创建检查点:

model.save_weights('weights')
status = model.load_weights('weights')

您可以使用 tf.train.Checkpoint 完全控制此过程。

x = tf.Variable(10.)
checkpoint = tf.train.Checkpoint(x=x)
x.assign(2.)   # Assign a new value to the variables and save.
checkpoint_path = './ckpt/'
checkpoint.save('./ckpt/')

政安晨执行:

x.assign(11.)  # Change the variable after saving.# Restore values from the checkpoint
checkpoint.restore(tf.train.latest_checkpoint(checkpoint_path))print(x)  # => 2.0

政安晨执行:

要保存和加载模型,tf.train.Checkpoint 会存储对象的内部状态,而无需隐藏变量。要记录 modeloptimizer 和全局步骤的状态,请将它们传递到 tf.train.Checkpoint:

model = tf.keras.Sequential([tf.keras.layers.Conv2D(16,[3,3], activation='relu'),tf.keras.layers.GlobalAveragePooling2D(),tf.keras.layers.Dense(10)
])
optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
checkpoint_dir = 'path/to/model_dir'
if not os.path.exists(checkpoint_dir):os.makedirs(checkpoint_dir)
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt")
root = tf.train.Checkpoint(optimizer=optimizer,model=model)root.save(checkpoint_prefix)
root.restore(tf.train.latest_checkpoint(checkpoint_dir))

政安晨执行:

注:在许多训练循环中,会在调用 tf.train.Checkpoint.restore 后创建变量。这些变量将在创建后立即恢复,并且可以使用断言来确保检查点已完全加载。

面向对象的指标

tf.keras.metrics 会被存储为对象。可以通过将新数据传递给可调用对象来更新指标,并使用 tf.keras.metrics.result 方法检索结果,例如:

m = tf.keras.metrics.Mean("loss")
m(0)
m(5)
m.result()  # => 2.5
m([8, 9])
m.result()  # => 5.5

政安晨执行:

摘要和 TensorBoard

TensorBoard 是一种可视化工具,用于了解、调试和优化模型训练过程。它使用在执行程序时编写的摘要事件。

您可以在 Eager Execution 中使用 tf.summary 记录变量摘要。例如,要每 100 个训练步骤记录一次 loss 的摘要,请运行以下代码:

logdir = "./tb/"
writer = tf.summary.create_file_writer(logdir)steps = 1000
with writer.as_default():  # or call writer.set_as_default() before the loop.for i in range(steps):step = i + 1# Calculate loss with your real train function.loss = 1 - 0.001 * stepif step % 100 == 0:tf.summary.scalar('loss', loss, step=step)
ls tb/

政安晨执行:

自动微分高级主题

动态模型

tf.GradientTape 也可以用于动态模型。下面这个回溯线搜索算法示例看起来就像普通的 NumPy 代码,但它的控制流比较复杂,存在梯度且可微分:

def line_search_step(fn, init_x, rate=1.0):with tf.GradientTape() as tape:# Variables are automatically tracked.# But to calculate a gradient from a tensor, you must `watch` it.tape.watch(init_x)value = fn(init_x)grad = tape.gradient(value, init_x)grad_norm = tf.reduce_sum(grad * grad)init_value = valuewhile value > init_value - rate * grad_norm:x = init_x - rate * gradvalue = fn(x)rate /= 2.0return x, value

自定义梯度

自定义梯度是重写梯度的一种简单方法。在前向函数中,定义相对于输入、输出或中间结果的梯度。例如,下面是在后向传递中裁剪梯度范数的一种简单方法:

@tf.custom_gradient
def clip_gradient_by_norm(x, norm):y = tf.identity(x)def grad_fn(dresult):return [tf.clip_by_norm(dresult, norm), None]return y, grad_fn

自定义梯度通常用来为运算序列提供数值稳定的梯度:

def log1pexp(x):return tf.math.log(1 + tf.exp(x))def grad_log1pexp(x):with tf.GradientTape() as tape:tape.watch(x)value = log1pexp(x)return tape.gradient(value, x)
# The gradient computation works fine at x = 0.
grad_log1pexp(tf.constant(0.)).numpy()

政安晨执行:

# However, x = 100 fails because of numerical instability.
grad_log1pexp(tf.constant(100.)).numpy()

政安晨执行:

在此例中,log1pexp 函数可以通过自定义梯度进行分析简化。下面的实现重用了在前向传递期间计算的 tf.exp(x) 值,通过消除冗余计算使其变得更加高效:

@tf.custom_gradient
def log1pexp(x):e = tf.exp(x)def grad(dy):return dy * (1 - 1 / (1 + e))return tf.math.log(1 + e), graddef grad_log1pexp(x):with tf.GradientTape() as tape:tape.watch(x)value = log1pexp(x)return tape.gradient(value, x)
# As before, the gradient computation works fine at x = 0.
grad_log1pexp(tf.constant(0.)).numpy()
# And the gradient computation also works at x = 100.
grad_log1pexp(tf.constant(100.)).numpy()

政安晨执行:

性能

在 Eager Execution 期间,计算会自动分流到 GPU。如果想控制计算运行的位置,可将其放在 tf.device('/gpu:0') 块(或 CPU 等效块)中:

import timedef measure(x, steps):# TensorFlow initializes a GPU the first time it's used, exclude from timing.tf.matmul(x, x)start = time.time()for i in range(steps):x = tf.matmul(x, x)# tf.matmul can return before completing the matrix multiplication# (e.g., can return after enqueing the operation on a CUDA stream).# The x.numpy() call below will ensure that all enqueued operations# have completed (and will also copy the result to host memory,# so we're including a little more than just the matmul operation# time)._ = x.numpy()end = time.time()return end - startshape = (1000, 1000)
steps = 200
print("Time to multiply a {} matrix by itself {} times:".format(shape, steps))# Run on CPU:
with tf.device("/cpu:0"):print("CPU: {} secs".format(measure(tf.random.normal(shape), steps)))# Run on GPU, if available:
if tf.config.experimental.list_physical_devices("GPU"):with tf.device("/gpu:0"):print("GPU: {} secs".format(measure(tf.random.normal(shape), steps)))
else:print("GPU: not found")

政安晨执行:

可以将 tf.Tensor 对象复制到不同设备来执行其运算:

if tf.config.experimental.list_physical_devices("GPU"):x = tf.random.normal([10, 10])x_gpu0 = x.gpu()x_cpu = x.cpu()_ = tf.matmul(x_cpu, x_cpu)    # Runs on CPU_ = tf.matmul(x_gpu0, x_gpu0)  # Runs on GPU:0

政安晨执行:

基准

对于计算量繁重的模型(如在 GPU 上训练的 ResNet50),Eager Execution 性能与 tf.function 执行相当。但是对于计算量较小的模型来说,这种性能差距会越来越大,并且在为有大量小运算的模型优化热代码路径方面,其性能还有待提升。

使用函数

虽然 Eager Execution 增强了开发和调试的交互性,但 TensorFlow 1.x 样式的计算图执行在分布式训练、性能优化和生产部署方面具有优势。为了弥补这一差距,TensorFlow 2.0 通过 tf.function API 引入了 function

写在最后

咱们匆匆忙忙完成了这篇指南的演绎,其实这里面很多知识点,这个篇幅已经很长了(12000余字),我就不在这里讲解了,这篇文章里就做为完整演绎的留档吧。(以供大家参考)

相关文章:

政安晨:示例演绎TensorFlow的官方指南(一){基础知识}

为什么要示例演绎? 既然有了官方指南,咱们在官方指南上看看就可以了,为什么还要写示例演绎的文章呢? 其实对于初步了解TensorFlow的小伙伴们而言,示例演绎才是最重要的。 官方文档已经假定了您已经具备了相当合适的…...

node - 与数据库交互

在Web开发中,与数据库交互是常见的需求,用于持久化存储、检索和操作数据。不同的后端技术和数据库类型(如关系型数据库和非关系型数据库)有着不同的交互方式。下面介绍几种常见的数据库交互方法。 关系型数据库 关系型数据库(如MySQL、PostgreSQL、SQLite)使用结构化查…...

速盾:2024年cdn在5g时代重要吗

在2024年,随着5G技术的普及与应用,内容分发网络(Content Delivery Network,CDN)在数字化时代中的重要性将进一步巩固和扩大。CDN是一种用于快速、高效地分发网络内容的基础设施,它通过将内容部署在全球各地…...

微信小程序(四十一)wechat-http的使用

注释很详细,直接上代码 上一篇 新增内容: 1.模块下载 2.模块的使用 在终端输入npm install wechat-http 没有安装成功vue的先看之前的一篇 微信小程序(二十)Vant组件库的配置- 如果按以上的成功配置出现如下报错先输入以下语句 …...

所有设计模式大全及学习链接

文章目录 创建型设计模式结构型设计模式行为型设计模式 创建型设计模式 一种创建对象的设计模式,它们提供了一种灵活的方式来创建对象,同时隐藏了对象的创建细节。以下是常见的创建型设计模式: 工厂方法模式(Factory Method Patte…...

【Java程序设计】【C00264】基于Springboot的原创歌曲分享平台(有论文)

基于Springboot的原创歌曲分享平台(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的原创歌曲分享平台 本系统分为平台功能模块、管理员功能模块以及用户功能模块。 平台功能模块:在平台首页可以查看首…...

2024年,要特别注意这两个方位

家居风水对每个家庭都非常重要,可在无形中影响到人们的事业、财富以及健康运势。俗话说:“风水轮流转”,2024年为甲辰龙年,斗转星移、九宫飞星将改变宫位,新一年的磁场即将启动,方位的吉凶也会重新变动&…...

【Chrono Engine学习总结】5-sensor-5.1-sensor基础并创建一个lidar

由于Chrono的官方教程在一些细节方面解释的并不清楚,自己做了一些尝试,做学习总结。 1、Sensor模块 Sensor模块是附加模块,需要单独安装。参考:【Chrono Engine学习总结】1-安装配置与程序运行 Sensor Module Tutorial Sensor …...

springboot/ssm学生信息管理系统Java学生在线选课考试管理系统

springboot/ssm学生信息管理系统Java学生在线选课考试管理系统 开发语言:Java 框架:springboot(可改ssm) vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库:mysql 5.…...

three.js 箭头ArrowHelper的实践应用

效果&#xff1a; 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div></div></el-main></…...

力扣hot2--哈希

推荐博客&#xff1a; for(auto i : v)遍历容器元素_for auto 遍历-CSDN博客 字母异位词都有一个特点&#xff1a;也就是对这个词排序之后结果会相同。所以将排序之后的string作为key&#xff0c;将排序之后能变成key的单词组vector<string>作为value。 class Solution …...

【正在更新】从零开始认识语音识别:DNN-HMM混合系统语音识别(ASR)原理

摘要 | Abstract 这是一篇对语音识别中的一种热门技术——DNN-HMM混合系统原理的透彻介绍。本文自2月10日开始撰写&#xff0c;计划一星期内写完。 1.前言 | Introduction 近期想深入了解语音识别(ASR)中隐马尔可夫模型(HMM)和深度神经网络-隐马尔可夫(DNN-HMM)混合模型&#…...

thinkphp+vue企业产品展示网站f7enu

本文首先介绍了企业产品展示网站管理技术的发展背景与发展现状&#xff0c;然后遵循软件常规开发流程&#xff0c;首先针对系统选取适用的语言和开发平台&#xff0c;根据需求分析制定模块并设计数据库结构&#xff0c;再根据系统总体功能模块的设计绘制系统的功能模块图&#…...

在Ubuntu22.04上部署ComfyUI

ComfyUI 是 一个基于节点流程的 Stable Diffusion 操作界面&#xff0c;可以通过流程&#xff0c;实现了更加精准的工作流定制和完善的可复现性。每一个模块都有特定的的功能&#xff0c;我们可以通过调整模块连接达到不同的出图效果&#xff0c;特点如下&#xff1a; 1.对显存…...

Springboot+vue的社区养老服务平台(有报告)。Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的社区养老服务平台&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的社区养老服务平台&#xff0c;采用M&#xff08;model&…...

计算机设计大赛 深度学习+opencv+python实现车道线检测 - 自动驾驶

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV56 数据集处理7 模型训练8 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &am…...

机器学习2---逻辑回归(基础准备)

逻辑回归是基于线性回归是直线分的也可以做多分类 ## 数学基础 import numpy as np np.pi # 三角函数 np.sin() np.cos() np.tan() # 指数 y3**x # 对数 np.log10(10) np.log2(2) np.e np.log(np.e) #ln(e)# 对数运算 # log(AB) log(A) logB np.log(3*4)np.log(3)np.log(4) #…...

JVM体系

JVM是一种虚拟的计算机&#xff0c;它模拟了一个完整的硬件系统&#xff0c;并运行在一个完全隔离的环境中。这意味着JVM可以看作是一个在操作系统之上的计算机系统&#xff0c;与VMware、Virtual Box等虚拟机类似。JVM的设计目标是提供一个安全、可靠、高效且跨平台的运行环境…...

.NET命令行(CLI)常用命令

本文用于记录了.NET软件开发全生命周期各阶段常用的一些CLI命令&#xff0c;用于开发速查。 .NET命令行&#xff08;CLI&#xff09;常用命令 项目创建&#xff08;1&#xff09;查看本机SDK&#xff08;2&#xff09;查看本机可以使用的.NET版本&#xff08;3&#xff09;生成…...

六、Redis之数据持久化及高频面试题

6.1 数据持久化 官网文档地址&#xff1a;https://redis.io/docs/manual/persistence/ Redis提供了主要提供了 2 种不同形式的持久化方式&#xff1a; RDB&#xff08;Redis数据库&#xff09;&#xff1a;RDB 持久性以指定的时间间隔执行数据集的时间点快照。AOF&#xff0…...

爬虫——ajax和selenuim总结

为什么要写这个博客呢&#xff0c;这个代码前面其实都有&#xff0c;就是结束了。明天搞个qq登录&#xff0c;这个就结束了。 当然也会更新小说爬取&#xff0c;和百度翻译&#xff0c;百度小姐姐的爬取&#xff0c;的对比爬取。总结嘛&#xff01;&#xff01;&#xff01;加…...

【Python】单元测试unittest框架

note 使用unittest框架进行单元测试是Python标准库的一部分&#xff0c;提供了编写测试用例、测试套件以及运行测试的能力。测试用例是继承自unittest.TestCase的类。在这个类中&#xff0c;你可以定义一系列的方法来测试不同的行为。每个测试方法都应该以test开头。 文章目录…...

(三十七)大数据实战——Solr服务的部署安装

前言 Solr是一个基于Apache Lucene的开源搜索平台&#xff0c;它提供了强大的全文搜索、分布式搜索和数据分析功能。Solr 可以用于构建高性能的搜索应用程序&#xff0c;支持从海量数据中快速检索和分析信息。Solr 使用倒排索引和先进的搜索算法&#xff0c;可实现快速而准确的…...

在Ubuntu22.04上部署FoooCUS2.1

Fooocus 是一款基于 Gradio的图像生成软件&#xff0c;Fooocus 是对 Stable Diffusion 和 Midjourney 设计的重新思考&#xff1a; 1、从 Stable Diffusion 学习&#xff0c;该软件是离线的、开源的和免费的。 2、从 Midjourney 中学到&#xff0c;不需要手动调整&#xff0c;…...

详解C语言中的野指针和assert断言

目录 1.野指针1.1 野指针成因1.1.1 指针未初始化1.1.2 指针越界访问1.1.3 指针指向的空间释放 1.2 如何规避野指针1.2.1 指针初始化1.2.2 小心指针越界1.2.3 指针变量不再使用时&#xff0c;及时置为NULL&#xff0c;指针使用之前检查1.2.4 避免返回局部变量的地址 2.assert断言…...

Vue源码系列讲解——模板编译篇【四】(文本解析器)

1. 前言 在上篇文章中我们说了&#xff0c;当HTML解析器解析到文本内容时会调用4个钩子函数中的chars函数来创建文本型的AST节点&#xff0c;并且也说了在chars函数中会根据文本内容是否包含变量再细分为创建含有变量的AST节点和不包含变量的AST节点&#xff0c;如下&#xff…...

微信小程序开发学习笔记《17》uni-app框架-tabBar

微信小程序开发学习笔记《17》uni-app框架-tabBar 博主正在学习微信小程序开发&#xff0c;希望记录自己学习过程同时与广大网友共同学习讨论。建议仔细阅读uni-app对应官方文档 一、创建tabBar分支 运行如下的命令&#xff0c;基于master分支在本地创建tabBar子分支&#x…...

《区块链公链数据分析简易速速上手小册》第5章:高级数据分析技术(2024 最新版)

文章目录 5.1 跨链交易分析5.1.1 基础知识5.1.2 重点案例&#xff1a;分析以太坊到 BSC 的跨链交易理论步骤和工具准备Python 代码示例构思步骤1: 设置环境和获取合约信息步骤2: 分析以太坊上的锁定交易步骤3: 跟踪BSC上的铸币交易 结论 5.1.3 拓展案例 1&#xff1a;使用 Pyth…...

【芯片设计- RTL 数字逻辑设计入门 15 -- 函数实现数据大小端转换】

文章目录 函数实现数据大小端转换函数语法函数使用的规则Verilog and Testbench综合图VCS 仿真波形 函数实现数据大小端转换 在数字芯片设计中&#xff0c;经常把实现特定功能的模块编写成函数&#xff0c;在需要的时候再在主模块中调用&#xff0c;以提高代码的复用性和提高设…...

Codeforces Round 925 (Div. 3) D. Divisible Pairs (Java)

Codeforces Round 925 (Div. 3) D. Divisible Pairs (Java) 比赛链接&#xff1a;Codeforces Round 925 (Div. 3) D题传送门&#xff1a;D.Divisible Pairs 题目&#xff1a;D.Divisible Pairs 题目描述 输出格式 For each test case, output a single integer — the num…...

【C语言】实现单链表

目录 &#xff08;一&#xff09;头文件 &#xff08;二&#xff09;功能实现 &#xff08;1&#xff09;打印单链表 &#xff08;2&#xff09;头插与头删 &#xff08;3&#xff09;尾插与尾删 &#xff08;4&#xff09; 删除指定位置节点 和 删除指定位置之后的节点 …...

Hive调优——合并小文件

目录 一、小文件产生的原因 二、小文件的危害 三、小文件的解决方案 3.1 小文件的预防 3.1.1 减少Map数量 3.1.2 减少Reduce的数量 3.2 已存在的小文件合并 3.2.1 方式一&#xff1a;insert overwrite (推荐) 3.2.2 方式二&#xff1a;concatenate 3.2.3 方式三&#xff…...

设计模式(行为型模式)责任链模式

目录 一、简介二、责任链模式2.1、处理器接口2.2、具体处理器类2.3、使用 三、优点与缺点 一、简介 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为设计模式&#xff0c;允许你将请求沿着处理者链进行传递&#xff0c;直到有一个处理者能够处理…...

HTTP和HTTPS区别!

http 是我们几乎天天都要打交道的东西&#xff0c;相关知识点有点多&#xff0c;所以也有不少面试必问的点&#xff0c;这里做了一些整理&#xff0c;帮且大家树立完整的 http 知识体系&#xff0c;对面试官说 so easy HTTP 的特点和缺点 特点&#xff1a;无连接、无状态、灵…...

麻将普通胡牌算法(带混)

最近在玩腾讯的麻将游戏,但是经常需要充值,于是就想自己实现一个简单的单机麻将游戏.第一个难点就是实现胡牌的判断.这里写一下心得. 术语 本文的胡牌是指手牌构成了3N2的牌型,即一对做将,剩下的牌均为刻子(3张一样的牌)或者顺子(3张连续的牌比如234饼). 下面就是一个14张牌…...

Rust结构体详解:定义、使用及方法

Rust 是一门强调安全性和性能的系统级编程语言&#xff0c;它引入了结构体&#xff08;struct&#xff09;作为一种自定义的数据类型&#xff0c;允许程序员以更加灵活的方式组织和操作数据。在本篇博客中&#xff0c;我们将深入探讨 Rust 结构体的定义、使用以及相关概念。 什…...

LeetCode、435. 无重叠区间【中等,贪心 区间问题】

文章目录 前言LeetCode、435. 无重叠区间【中等&#xff0c;贪心 区间问题】题目链接及分类思路贪心、区间问题 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技…...

【实战】一、Jest 前端自动化测试框架基础入门(三) —— 前端要学的测试课 从Jest入门到TDD BDD双实战(三)

文章目录 一、Jest 前端自动化测试框架基础入门7.异步代码的测试方法8.Jest 中的钩子函数9.钩子函数的作用域 学习内容来源&#xff1a;Jest入门到TDD/BDD双实战_前端要学的测试课 相对原教程&#xff0c;我在学习开始时&#xff08;2023.08&#xff09;采用的是当前最新版本&a…...

信息学奥赛一本通1228:书架

1228&#xff1a;书架 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 18190 通过数: 10557 【题目描述】 John最近买了一个书架用来存放奶牛养殖书籍&#xff0c;但书架很快被存满了&#xff0c;只剩最顶层有空余。 John共有N&#xfffd;头奶牛(1≤N≤20,0001≤…...

红队打靶练习:GLASGOW SMILE: 1.1

目录 信息收集 1、arp 2、nmap 3、nikto 4、whatweb 目录探测 1、gobuster 2、dirsearch WEB web信息收集 /how_to.txt /joomla CMS利用 1、爆破后台 2、登录 3、反弹shell 提权 系统信息收集 rob用户登录 abner用户 penguin用户 get root flag 信息收集…...

网络安全的今年:量子、生成人工智能以及 LLM 和密码

尽管世界总是难以预测&#xff0c;但网络安全的几个强劲趋势表明未来几个月的发展充满希望和令人担忧。有一点是肯定的&#xff1a;2024 年将是非常重要且有趣的一年。 近年来&#xff0c;人工智能&#xff08;AI&#xff09;以令人难以置信的速度发展&#xff0c;其在网络安全…...

【FPGA】Verilog:奇偶校验位发生器 | 奇偶校验位校验器

目录 0x00 奇偶校验位发生器 0x01 奇偶校验位校验器 0x02 错误检测器和纠错器...

【心得】关于STM32中RTC的校准方法

最近看了一些关于RTC校准的帖子&#xff0c;发现很多人存在疑惑。正好最近我也在STM32中实现了RTC校准。发些心得。这些对老手来说有些罗索&#xff0c;但对新手有益处。 实现RTC 校准的核心之一是库文件Stm321f0x_bkp.c中的void BKP_SetRTCCalibrationValue (uint8_t Calibra…...

消息中间件面试篇

目录 消息中间件 RabbitMQ 消息不丢失 生产者确认机制 消息持久化 交换机持久化 队列持久化 消息持久化 消费者确认 消息重复消费 出现的场景 解决方案 每条消息设置一个唯一的标识id 幂等方案&#xff1a;【 分布式锁、数据库锁&#xff08;悲观锁、乐观锁&#…...

【MySQL】-20 MySQL综合-6(MySQL创建数据表+MySQL修改数据表+MySQL删除数据表)

MySQL创建数据表MySQL修改数据表MySQL删除数据表 MySQL创建数据表基本语法在指定的数据库中创建表查看表结构 MySQL修改数据表基本语法添加字段修改字段数据类型删除字段修改字段名称修改表名 MySQL删除数据表基本语法删除表 MySQL创建数据表 在创建数据库之后&#xff0c;接下…...

linux查看当前连接的IP

linux下查询当前所有连接的ip_linux查看某个ip的连接-CSDN博客 netstat -ntu | grep tcp | awk {print $5} | cut -d: -f1 | sort | uniq -c | sort -nr...

洛谷_P1923 【深基9.例4】求第 k 小的数_python写法

哪位大佬可以出一下这个的题解&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;话说蓝桥杯可以用numpy库吗&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f; 这道题有一个很简单的思路就是排序完成之后再访问。 but有很大的问题&…...

【MySQL】学习约束和使用图形化界面创建表

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-iqtbME2KmWpQFQSt {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…...

QGIS编译(跨平台编译)之四十八:pixman编译(Windows、Linux、MacOS环境下编译)

文章目录 一、pixman介绍二、pixman下载三、Linux下编译四、MacOS下编译五、Windows下编译一、pixman介绍 Pixman 是一个开源的图形库,它提供了底层像素操作功能,包括像素格式转换、图像合成、图像缩放、图像旋转等多种操作。Pixman 主要被用作 Cairo 图形库的后端,支持 Ca…...

华为数通方向HCIP-DataCom H12-821题库(单选题:441-460)

第441题 下面是一台路由输出的信息,关于这段信息描述正确的是 <R1>display bgp peerBGP local router ID : 2.2.2.2Local AS number : 100Total number of peers : 2 Peers in established state : 0Peer V AS MsgRcvd MsgSent OutQ Up/Down …...