如何从头开始构建神经网络?(附教程)

随着流行的深度学习框架的出现,如 TensorFlow、Keras、PyTorch 以及其他类似库,学习神经网络对于新手来说变得更加便捷。虽然这些框架可以让你在几分钟内解决最复杂的计算任务,但它们并不要求你理解背后所有需求的核心概念和直觉。如果你知道特定函数如何工作,并且能在代码块中准确地使用它,就可以轻松地解决大多数问题。然而,要真正理解神经网络的概念以及完整的工作流程,从零开始学习人工神经网络的工作原理是至关重要的。这些神经网络是如何解决复杂问题的呢?

对于任何对人工智能和深度学习感兴趣的人,理解神经网络的原理以及构建过程都是一项有价值的探索。尽管我们暂时不使用深度学习框架如 TensorFlow、Keras 或 PyTorch,但我们将利用 NumPy 等库来进行数值矩阵计算。通过 NumPy 数组,我们可以进行模拟深度学习效果的复杂计算,并借此理解神经网络的编程流程。借助从头开始构建的这些神经网络,我们将实现一些简单的神经网络解决方案。

准备工作

为了跟进本文,你需要具备一些 Python 编程经验,并对深度学习有初步了解。我们假设所有读者都能访问足够强大的设备以运行提供的代码。

如果你还没有合适的 GPU,建议使用GPU云服务。因为这是最快、相对低成本获得 GPU,且可以简单灵活完成配置的方式。Digital Ocean 的 GPU Droplets 提供 H100 实例,近期限时优惠仅需 2.5刀/小时,点击这里了解 GPU Droplets 更多信息。

关于如何开始使用 Python 代码,我们建议你尝试这个初学者指南,以设置你的系统并准备运行初学者教程。

先了解一些概念

神经网络是深度学习和人工智能未来中最引人入胜的话题之一。虽然“人工神经网络”一词只是受到生物神经元概念的启发,但在构建这些网络时有一些明显的相似之处值得注意。就像人类神经元一样,使用人工神经网络的有趣的地方在于,我们通常可以确定它们在做什么,但很难确切知道它们是如何工作并实现目标的。尽管我们可以回答一些“xx是什么”的问题,但要完全理解模型的行为仍需进一步探索。这就是“黑盒”深度学习的来源,这个称呼适用于许多深度学习系统。不过,有许多神经网络是可解释的,使我们能够轻松地解释其目的和方法,这也取决于具体的用例。

人工智能是一个涉猎广泛的领域,而深度学习和神经网络只是其中的两个子域。在本文中,我们的主要目标是深入理解神经网络的概念,并展示如何在不使用一些知名和流行的深度学习框架的情况下从零开始构建一个架构。在深入学习如何从零实现神经网络之前,让我们直观地了解它们的工作原理。

理解神经元的概念

大多数数学运算可以通过函数连接。函数是神经网络学习几乎任何事物的最基本概念之一。无论函数具体实现什么,神经网络都可以被设计成近似该函数。这便是著名的普遍近似定理,它赋予神经网络处理各种不同挑战的能力,同时也带来了黑盒的特性。

许多现实世界的问题,如计算机视觉任务和自然语言处理任务,也可以表示为相互关联的函数。例如,通过函数,我们可以将几个输入单词映射到特定的输出单词,或将一组图像与各自的输出图像相连。数学和现实世界问题中的大多数概念都可以被重构为函数,从而框定问题并让神经网络找到适当的解决方案。

什么是人工神经网络?它是如何工作的?

人工神经网络通常被称为神经网络、神经网或 NNs。这些网络受到生物神经元的启发。需要再次强调的是,实际上,生物神经元与用于构建神经网络架构的“神经元”之间几乎没有直接关联。尽管两者的基本工作方式截然不同,但它们的共同点在于,结合在一起时,这些“神经元”可以相对容易地解决复杂任务。

为了理解神经网络的基本工作原理,线性方程“y = mx + c”是帮助理解神经网络的关键数学概念之一。方程中的“y = mx”部分帮助操控线条,获得所需的形状和数值。而另一个值,截距“c”,则通过改变在 y 轴上的位置来调整线条的位置。请参见以下两张图,以更清楚地了解此基本概念。

在神经网络中,Y=WX+B可以用来表示这个方程,Y代表输出值,w代表需要调整的权重,x代表输入值,b代表值,通过使用这个简单的逻辑,神经网络可以使用已知的信息‘b’和‘w’来确定‘x’的值。

为了更好地理解权重和偏差这一特定概念,我们可以通过如下所示的简单代码片段和结果输出来进行探索。通过一些输入值、权重和偏差,我们可以使用输入值与权重转置值的点乘积来计算输出。在得到的结果值上,再添加相应的偏差来得到所需的值。下面的示例相对简单,但足以建立基本理解。不过,在下一节和即将发布的文章中,我们将介绍更复杂的概念。

import numpy as np
inputs = [1, 2, 3, 2.5]
weights = [[ 0.2, 0.8, - 0.5, 1 ],[ 0.5, - 0.91, 0.26, - 0.5 ],[ - 0.26, - 0.27, 0.17, 0.87 ]]
biases = [2, 3, 0.5]
outputs = np.dot(weights, inputs) + biases

Or Use this methodnp.dot(inputs, weights.T) + biasesprint (outputs)

[4.8   1.21  2.385]

当神经网络组合在一起时,它们能够在反向传播的帮助下通过训练过程进行学习。第一步是前向传播,即通过使用随机权重计算每一层直到输出单元所需的信息。然而,这些随机权重通常永远不会接近完美,需要调整权重才能获得更理想的结果。因此,神经网络中的反向传播是其功能中更重要的方面之一。反向传播是操纵和调整权重的地方,通常通过比较手头的输出和预期的输出。我们将在下一节和即将发表的文章中进一步探讨这些概念。

从零开始构建神经网络

在本节中,我们将学习如何从零开始构建神经网络来解决一些任务。在开始构建神经网络之前,先了解我们要解决的问题类型。目标是构建能够理解和解决逻辑门功能的神经网络,例如 AND、OR、NOT、XOR 等逻辑门。对于这个特定示例,我们将研究如何通过从头构建神经网络来解决 XOR 门问题。

逻辑门是电子元件的基本构建块之一。选择这些逻辑门是因为每个门都基于特定的逻辑运行。例如,XOR 门仅在两个输入值不同时输出高电平;如果两个输入值相同,输出为低电平。这些逻辑通常通过真值表表示。上图展示了 XOR 门的符号和真值表表示。我们可以使用数组形式的输入和输出值来训练构建的神经网络,以获得理想结果。

首先,导入构建神经网络所需的库。在本节中,不使用任何深度学习框架,仅使用 NumPy 来简化复杂的张量和数学计算。即使没有 NumPy 库,你也可以选择手动构建神经网络,但这会耗费更多时间。本节唯一的其他库是 matplotlib,用于可视化损失并绘制模型在特定训练时期后的变化。

import numpy as np
import matplotlib.pyplot as plt

让我们描述真值表的输入和 XOR 门的预期输出。读者可以选择使用不同的门并进行相应的实验(请注意,有时你可能无法获得所需的结果)。以下是 XOR 门的输入变量和预期结果的代码片段。

a = np.array([0, 0, 1, 1])
b = np.array([0, 1, 0, 1])

# y_and = np.array([[0, 0, 0, 1]])
y_xor = np.array([[0,1,1,0]])

让我们将输入组合成一个数组实体,这样我们就有了一个总输入数组和一个输出数组供神经网络学习。这个组合过程可以通过几种方式完成。在下面的代码块中,我们使用一个列表来组合两个数组,然后将最终列表转换回 numpy 数组格式。在下一节中,我还提到了另一种组合输入数据的方法。

total_input = []

total_input = [a, b]

total_input = np.array(total_input)

得到的输入数组如下所示:

array([[0, 0, 1, 1],
       [0, 1, 0, 1]])

对于大多数神经网络问题,数组的形状是最关键的概念。形状不匹配是解决此类任务时最有可能出现的错误。因此,让我们打印并分析输入数组的形状。

(2, 4)

现在让我们定义一些从头开始构建神经网络所需的基本参数。节点的激活函数定义给定一个输入或一组输入时该节点的输出。我们将首先定义 S 型函数,这将是我们执行此任务的主要激活函数。然后,我们将继续定义一些基本参数,例如输入神经元、隐藏神经元、输出神经元的数量、总训练样本以及我们将训练神经网络的学习效率。

# Define the sigmoid activation function:
def sigmoid (x):
    return 1/(1 + np.exp(-x))

# Define the number of neurons
input_neurons, hidden_neurons, output_neurons = 2, 2, 1

# Total training examples
samples = total_input.shape[1]

# Learning rate
lr = 0.1

# Define random seed to replicate the outputs
np.random.seed(42)

下一步,我们将初始化将通过隐藏层和输出层的权重,如下面的代码片段所示。随机化权重而不是为其分配零值通常是一个好主意,因为神经网络有时可能无法学习所需的结果。

# Initializing the weights for hidden and output layers

w1 = np.random.rand(hidden_neurons, input_neurons)
w2 = np.random.rand(output_neurons, hidden_neurons)

在下一个代码块中,我们将定义神经网络模型的工作结构。首先,我们将使函数通过神经网络结构执行前向传播。我们将首先计算隐藏层中的权重和输入值,然后将它们传递给我们的 S 型激活函数。然后,我们也将对输出层执行类似的传播,其中我们将利用我们之前定义的第二个权重。随机生成的权重显然无法达到预期的结果,需要进行微调。因此,我们还将实现反向传播机制,以帮助我们的模型更有效地训练。此操作的执行方式与我们在上一节中讨论的方式类似。

# Forward propagation
def forward_prop(w1, w2, x):
    z1 = np.dot(w1, x)
    a1 = sigmoid(z1)
    z2 = np.dot(w2, a1)
    a2 = sigmoid(z2)
    return z1, a1, z2, a2

# Backward propagation
def back_prop(m, w1, w2, z1, a1, z2, a2, y):

    dz2 = a2-y
    dw2 = np.dot(dz2, a1.T)/m
    dz1 = np.dot(w2.T, dz2) * a1*(1-a1)
    dw1 = np.dot(dz1, total_input.T)/m
    dw1 = np.reshape(dw1, w1.shape)

    dw2 = np.reshape(dw2,w2.shape)
    return dz2,dw2,dz1,dw1

现在我们已经定义了前向传播和后向传播机制,可以开始训练神经网络了。让我们进行一个训练循环,运行预定义的迭代次数。首先,我们利用前向传播来获取输出值,然后将其与预期输出进行比较,开始计算相应的损失。开始执行神经网络的反向传播后,我们就可以微调权重,以接近预期的最终结果。以下是训练过程的代码块,我们还确保损失不断减少,表明神经网络正在学习如何预测所需结果,并附带相应图表。

losses = []
iterations = 10000

for i in range(iterations):
    z1, a1, z2, a2 = forward_prop(w1, w2, total_input)
    loss = -(1/samples)*np.sum(y_xor*np.log(a2)+(1-y_xor)*np.log(1-a2))
    losses.append(loss)
    da2, dw2, dz1, dw1 = back_prop(samples, w1, w2, z1, a1, z2, a2, y_xor)
    w2 = w2-lr*dw2
    w1 = w1-lr*dw1

# We plot losses to see how our network is doing
plt.plot(losses)
plt.xlabel("EPOCHS")
plt.ylabel("Loss value")

让我们定义预测函数,通过该函数我们可以利用经过训练的神经网络来计算一些预测。我们将执行前向传播并压缩获得的结果。由于我们在训练过程中对权重进行了微调,因此我们应该能够以 0.5 的阈值实现所需的结果。

# Creating the predict function

def predict(w1,w2,input):
    z1, a1, z2, a2 = forward_prop(w1,w2,test)
    a2 = np.squeeze(a2)

    if a2>=0.5:
        print("For input", [i[0] for i in input], "output is 1")
    else:
        print("For input", [i[0] for i in input], "output is 0")

现在我们已经完成了预测函数的定义,我们可以测试你构建的神经网络所做的预测,并在对模型进行约 10000 次迭代训练后查看其性能。我们将测试四种可能情况中的每一种预测结果,并将它们与 XOR 门的预期结果进行比较。

test = np.array([[0],[0]])
predict(w1,w2,test)
test = np.array([[0],[1]])
predict(w1,w2,test)
test = np.array([[1],[0]])
predict(w1,w2,test)
test = np.array([[1],[1]])
predict(w1,w2,test)

For input [0, 0] output is 0
For input [0, 1] output is 1
For input [1, 0] output is 1
For input [1, 1] output is 0

我们可以注意到,神经网络的预测结果与预期结果相似。因此可以得出结论,从零构建的神经网络成功地准确预测了 XOR 门任务。本节中的大部分代码参考了以下 GitHub 资源。如果你想要另一个学习资源,建议查看它。同时,鼓励读者通过从头构建神经网络来尝试解决不同类型的逻辑门,以探索它们的其他变体。

使用深度学习框架的构建进行比较

深度学习和人工神经网络的领域非常广阔。虽然可以从头开始构建神经网络来解决复杂的问题,但由于需要大量的时间以及需要构建的网络的固有复杂性,这通常是不可行的。因此,我们使用深度学习框架(如 TensorFlow、PyTorch、MXNet、Caffe 和其他类似的库(或工具))来设计、训练和验证神经网络模型。

这些深度学习框架允许开发人员和研究人员快速构建他们想要的模型来解决特定任务,而无需在复杂和不必要的细节的底层工作上投入太多。在众多可用的深度学习框架中,目前最流行的两种构建神经网络的工具是 TensorFlow 和 PyTorch。在本节中,我们将借助深度学习框架重建我们在前面几节中构建的项目。

对于这个重建项目,我将使用 TensorFlow 和 Keras 库。以下是我们用于构建神经网络以解决与门和异或门的导入列表。

import tensorflow as tf
from tensorflow import keras
import numpy as np

导入必要的库后,我们可以定义一些必需的参数,我们将利用这些参数构建神经网络来学习与门的输出。与与门类似,我们也将像上一节中那样构建异或门。首先,让我们看看与门的构造。下面是与门的输入和预期结果。与门的逻辑是,只有当两个(或所有)输入都为高时,输出才为高。否则,当任一输入为低时,输出也为低。

a = np.array([0, 0, 1, 1])
b = np.array([0, 1, 0, 1])

y_and = np.array([0, 0, 0, 1])

我们声明了输入和预期输出,就该将两个输入数组组合成一个实体了。我们可以通过几种方法来实现这一点,如上一节所述。对于此代码片段,我们将它们附加到一个包含四个单独元素的列表中,每个列表都有两个元素。组合输入元素后获得的最终数组将存储在一个新数组中。

total_input = []for i, j in zip(a, b):
    input1 = []
    input1.append(i)
    input1.append(j)
    total_input.append(input1)
total_input = np.array(total_input)

两个初始输入列表组合后得到的输入数组如下所示。

array([[0, 0],[0, 1],[1, 0],[1, 1]])

这个最终输入数组的形状如下。

(4, 2)

下一步,我们将创建训练数据及其各自的输出标签。首先,我们将创建列表来存储输入和输出的训练数据。我们完成这些元素的循环后,我们就可以将这些列表保存为数组,并使用它们进行进一步的计算和神经网络训练。

x_train = []
y_train = []for i, j in zip(total_input, y_and):
    x_train.append(i)
    y_train.append(j)
x_train = np.array(x_train)
y_train = np.array(y_train)

此类任务的训练过程非常简单。我们可以定义所需的库,即输入层、隐藏层和输出节点的密集层,最后是顺序模型,以便我们可以构建顺序类型模型来解决所需的 AND 门任务。首先,我们将定义模型的类型,然后继续添加输入层,它将按照我们之前的定义接受输入。我们有两个隐藏层,每个隐藏层有十个节点,并带有 ReLU 激活函数。最终的输出层包含一个节点的 Sigmoid 激活函数,为我们提供所需的结果。根据提供的输入,最终输出为零或一。

from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Sequential
model = Sequential()
model.add(Input(shape = x_train[0].shape))
model.add(Dense(10, activation = "relu"))
model.add(Dense(10, activation = "relu"))
model.add(Dense(1, activation = "sigmoid"))
model.summary()

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
dense (Dense)                (None, 10)                30
_________________________________________________________________
dense_1 (Dense)              (None, 10)                110
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 11
=================================================================
Total params: 151
Trainable params: 151
Non-trainable params: 0
_________________________________________________________________

上表显示了包含隐藏层和输出节点及其各自参数的顺序类型网络的摘要。现在我们已经构建了模型架构来解决所需的 AND 门任务,我们可以继续编译模型并对其进行相应的训练。我们将利用 Adam 优化器、二元交叉熵损失函数,并计算二元准确度来验证我们的模型有多准确。

model.compile(optimizer = "adam", loss = "binary_crossentropy", metrics = "binary_accuracy")

模型编译完成,让我们开始训练过程,看看模型是否能够达到预期的结果。请注意,从头开始的神经网络的损失函数和优化器等内容尚未涵盖。我们将在未来的文章中介绍这些概念。下面是训练所需模型的代码片段。

model.fit(x_train, y_train, epochs = 500)

我们将对模型进行大约 500 个时期的训练,以确保它能够按预期学习要求。由于这些门控任务的数据较少,因此模型将需要更多的训练来学习并相应地优化结果。训练完成后(大约需要几分钟),我们可以继续使用预测函数来验证获得的结果。让我们对数据集执行预测,如下面的代码片段所示。

model.predict(x_train)

array([[0.00790971],
       [0.02351646],
       [0.00969902],
       [0.93897456]], dtype=float32)

我们可以注意到,AND 门的结果与预期的差不多。对于必须为零的输出值,预测得到的结果能够预测接近零的值,而对于必须为 1 的输出值,我们得到的结果接近 1。我们还可以对这些值进行四舍五入以获得所需的结果。除了我们刚刚完成的 AND 门之外,让我们探索另一个门。

同样,对于 XOR 门,我们也可以继续遵循与 AND 门类似的工作流程。首先,我们将定义 XOR 门所需的输入。它再次是一个 2 通道输入,利用变量 a 和 b 存储输入值。y 变量将把预期的结果值存储在 NumPy 数组中。我们将以类似于本节中使用的方法组合这两个输入数组。输入组合起来,我们得到了所需的组合,我们将数据分为训练输入信息及其结果标签输出。

a = np.array([0, 0, 1, 1])
b = np.array([0, 1, 0, 1])

y_xor = np.array([0, 1, 1, 0])

total_input = []

for i, j in zip(a, b):
    input1 = []
    input1.append(i)
    input1.append(j)
    total_input.append(input1)

total_input = np.array(total_input)

x_train = []
y_train = []

for i, j in zip(total_input, y_xor):
    x_train.append(i)
    y_train.append(j)

x_train = np.array(x_train)
y_train = np.array(y_train)

我们将使用与本文本节前面类似的顺序类型架构。代码片段和模型的最终摘要如下所示:

model1 = Sequential()
model1.add(Input(shape = x_train[0].shape))
model1.add(Dense(10, activation = "relu"))
model1.add(Dense(10, activation = "relu"))
model1.add(Dense(1, activation = "sigmoid"))

model1.summary()

Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
dense_3 (Dense)              (None, 10)                30
_________________________________________________________________
dense_4 (Dense)              (None, 10)                110
_________________________________________________________________
dense_5 (Dense)              (None, 1)                 11
=================================================================
Total params: 151
Trainable params: 151
Non-trainable params: 0
_________________________________________________________________

我们将定义优化器和损失函数等参数来编译模型,然后拟合模型。对于训练过程,我们将使用第二个模型和新的训练数据输入和输出进行训练。我们将对我们的模型进行一千次训练,然后获得最佳预测。由于要训练的数据样本相对较少,因此训练只需几分钟。

model1.compile(optimizer = "adam", loss = "binary_crossentropy", metrics = "binary_accuracy")

model1.fit(x_train, y_train, epochs = 1000)

让我们对训练输入数据进行预测,并查看训练过程完成后模型能够预测的输出。

model1.predict(x_train)

array([[0.01542357],[0.995468  ],[0.99343044],[0.00554709]], dtype=float32)

我们可以注意到,输出值与相应的预期结果非常准确。当预期结果为零时,值更接近零,当预期结果为一时,值更接近一。最后,让我们分别对 AND 门和 XOR 门模型的两个预测值进行四舍五入。执行此步骤将帮助我们获得预期输出所需的单个整数值。

model.predict(x_train).round()
model1.predict(x_train).round()

array([[0.],[0.],[0.],[1.]], dtype=float32)

array([[0.],[1.],[1.],[0.]], dtype=float32)

我们可以注意到,经过训练的两个模型都能够利用提供的输入生成理想的输出。即使我们的数据量较少,经过长时间的训练,该模型也能够在减少损失的情况下实现预期结果。从头开始学习神经网络所有基本知识的工作原理是相当漫长的。优化器、损失函数、各种损失函数和其他类似主题等复杂概念将在未来的关于从头构建神经网络的文章中介绍。

结论

在本文中,我们展示了从头构建神经网络的大部分基本概念。在简要介绍之后,我们探讨了理解人工神经网络工作原理所需的一些关键要素。掌握了基本概念后,我们开始使用 NumPy 从头构建神经网络,并尝试了一个可以解决 XOR 门问题的 ANN。最后,我们还学习了如何使用深度学习框架(如 TensorFlow 和 Keras)构建 AND 和 XOR 等逻辑门的解决方案。

人工神经网络 (ANN) 和深度学习带来了一场革命,使机器能够完成一些曾经被认为不可能的复杂任务。成功的人工智能和神经网络之旅从简单的感知器模型开始,逐步迈向带有 n 个隐藏层的复杂架构。随着 GPU 的普及和经济实惠的计算资源的普及,任何有兴趣学习如何创建此类模型和框架的人都可以更容易地开始。神经网络的复杂性和概念繁多,尤其是当我们尝试从零开始构建这些网络时,就像我们在本文中所做的那样。在未来的部分中,我们将进一步探索从头构建神经网络的更多基础。

当然如果你还没找到合适的 GPU,但是有希望训练大模型,欢迎尝试 Digitalocean 的

在接下来的文章中,我们将研究更多生成对抗网络的变体,例如 pix-2-pix GAN、BERT Transformer,当然还有从头构建神经网络的第二部分。在此之前,继续探索和学习新知识吧!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[flask][html]如何取消marker伪元素

【背景】 flask做项目时,导航栏默认出现小圆点,很难看,希望能够去除。 【分析】 前端查看后,发现是自动生成的伪元素::marker。 【方法】 找到相应的标签,我的情况是li,追加style。 style="list-style: none;"完整li部分: <li class="</

02-分布式对象存储设计原理

02-分布式对象存储设计原理 保存图片、音视频等大文件就是对象存储&#xff1a; 很好的大文件读写性能 还可通过水平扩展实现近乎无限容量 并兼顾服务高可用、数据高可靠 对象存储“全能”&#xff0c;主要因为&#xff0c;对象存储是原生分布式存储系统&#xff0c;相比MySQL、…

【论文复现】STM32设计的物联网智能鱼缸

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀STM32设计的物联网智能鱼缸 【1】项目功能介绍【2】设计需求总结【3】项目硬件模块组成 1.2 设计思路【1】整体设计思路【2】ESP8266工作模式…

『OpenCV-Python』视频的读取和保存

点赞 + 关注 + 收藏 = 学会了 推荐关注 《OpenCV-Python专栏》 上一讲介绍了 OpenCV 的读取图片的方法,这一讲简单聊聊 OpenCV 读取和保存视频。 视频的来源主要有2种,一种是本地视频文件,另一种是实时视频流,比如手机和电脑的摄像头。 要读取这两种视频的方法都是一样的…

2024智能机器人与自动控制国际学术会议 (IRAC 2024)

主办&#xff0c;承办&#xff0c;支持单位 会议官网 www.icirac.org 大会时间&#xff1a;2024年11月29-12月1日 大会简介 2024智能机器人与自动控制国际学术会议 &#xff08;IRAC 2024&#xff09;由华南理工大学主办&#xff0c;会议将于2024年11月29日-12月1日在中国广…

table详细用法

注意&#xff1a;table元素上的很多属性都已经被废弃了&#xff0c;建议使用css方式替代。 表格的box-sizing默认值为border-box 例如&#xff1a; border-collapse属性 border-collapse CSS 属性是用来决定表格的边框是分开&#xff08;separate&#xff09;默认值的还是合并…

【STM32】基于SPI协议读写SD,详解!

文章目录 0 前言1 SD卡的种类和简介1.1 SD卡的种类1.2 SD卡的整体结构1.3 SD卡运行机制——指令和响应2 SD卡的通信总线2.1 SDIO2.2 SPI3 硬件连接4 代码实践【重点】4.1 HAL库移植4.2 标准库移植4.3 遇到的问题和解决方案5 扩展阅读0 前言 因为项目需要,使用stm32读写sd卡,这…

ZooKeeper单机、集群模式搭建教程

单点配置 ZooKeeper在启动的时候&#xff0c;默认会读取/conf/zoo.cfg配置文件&#xff0c;该文件缺失会报错。因此&#xff0c;我们需要在将容器/conf/挂载出来&#xff0c;在制定的目录下&#xff0c;添加zoo.cfg文件。 zoo.cfg logback.xml 配置文件的信息可以从二进制包…

如何在Mysql中生成0-23完整的小时数据

目录 1. 创建表2. 插入0-23小时的数据3. 查询并合并数据 在数据分析中&#xff0c;我们经常需要对特定时间段内的数据进行统计和分析。 例如&#xff0c;在名片进线的场景中&#xff0c;我们可能需要了解一天内每小时的名片进线数量。 然而&#xff0c;由于某些时间点可能没有数…

厦门凯酷全科技有限公司正规吗?

在这个短视频风起云涌的时代&#xff0c;抖音作为电商领域的黑马&#xff0c;正以惊人的速度改变着消费者的购物习惯与品牌的市场策略。在这场变革中&#xff0c;厦门凯酷全科技有限公司凭借其专业的抖音电商服务&#xff0c;在众多服务商中脱颖而出&#xff0c;成为众多品牌信…

SpringBoot配置类

在Spring Boot中&#xff0c;配置类是一种特殊的类&#xff0c;用于定义和配置Spring应用程序的各种组件、服务和属性。这些配置类通常使用Java注解来声明&#xff0c;并且可以通过Spring的依赖注入机制来管理和使用。 Spring 容器初始化时会加载被Component、Service、Reposi…

ADS项目笔记 1. 低噪声放大器LNA天线一体化设计

在传统射频结构的设计中&#xff0c;天线模块和有源电路部分相互分离&#xff0c;两者之间通过 50 Ω 传输线级联&#xff0c;这种设计需要在有源电路和天线之间建立无源网络&#xff0c;包括天线模块的输入匹配网络以及有源电路的匹配网络。这些无源网络不仅增加了系统的插入损…

Vue2+ElementUI:用计算属性实现搜索框功能

前言&#xff1a; 本文代码使用vue2element UI。 输入框搜索的功能&#xff0c;可以在前端通过计算属性过滤实现&#xff0c;也可以调用后端写好的接口。本文介绍的是通过计算属性对表格数据实时过滤&#xff0c;后附完整代码&#xff0c;代码中提供的是死数据&#xff0c;可…

【目标检测】用YOLOv8-Segment训练语义分割数据集(保姆级教学)

前言 这篇教程会手把手带你用 YOLOv8-Segment 搭建一个属于自己的分割任务项目。从环境配置到数据集准备&#xff0c;再到模型训练和测试&#xff0c;所有步骤都有详细说明&#xff0c;适合初学者使用。你将学会如何安装必要的软件&#xff0c;标注自己的数据&#xff0c;并使…

Elasticsearch:管理和排除 Elasticsearch 内存故障

作者&#xff1a;来自 Elastic Stef Nestor 随着 Elastic Cloud 提供可观察性、安全性和搜索等解决方案&#xff0c;我们将使用 Elastic Cloud 的用户范围从完整的运营团队扩大到包括数据工程师、安全团队和顾问。作为 Elastic 支持代表&#xff0c;我很乐意与各种各样的用户和…

前深度学习时代-经典的推荐算法

参考自《深度学习推荐系统》—— 王喆&#xff0c;用于学习记录。 1.协同过滤 “协同过滤”就是协同大家的反馈、评价和意见一起对海量的信息进行过滤&#xff0c;从中筛选出目标用户可能感兴趣的信息的推荐过程。 基于用户相似度进行推荐的协同过滤算法 UserCF 用户相似度…

两行命令搭建深度学习环境(Docker/torch2.5.1+cu118/命令行美化+插件),含完整的 Docker 安装步骤

深度学习环境的配置过于繁琐&#xff0c;所以我制作了两个基础的镜像&#xff0c;希望可以帮助大家节省时间&#xff0c;你可以选择其中一种进行安装&#xff0c;版本说明&#xff1a; base 版本基于 pytorch/pytorch:2.5.1-cuda11.8-cudnn9-devel&#xff0c;默认 python 版本…

WebRTC视频 04 - 视频采集类 VideoCaptureDS 中篇

WebRTC视频 01 - 视频采集整体架构 WebRTC视频 02 - 视频采集类 VideoCaptureModule WebRTC视频 03 - 视频采集类 VideoCaptureDS 上篇 WebRTC视频 04 - 视频采集类 VideoCaptureDS 中篇&#xff08;本文&#xff09; WebRTC视频 05 - 视频采集类 VideoCaptureDS 下篇 一、前言…

AI在电商平台中的创新应用:提升销售效率与用户体验的数字化转型

1. 引言 AI技术在电商平台的应用已不仅仅停留在基础的数据分析和自动化推荐上。随着人工智能的迅速发展&#xff0c;越来越多的电商平台开始将AI技术深度融合到用户体验、定价策略、供应链优化、客户服务等核心业务中&#xff0c;从而显著提升运营效率和用户满意度。在这篇文章…

Blossom:开源私有部署的markdown笔记软件

在信息化、数字化时代&#xff0c;我们每个人的生活和工作都离不开笔记和知识管理。从简单的待办事项&#xff0c;到复杂的项目计划&#xff0c;再到存储大量个人知识的工具&#xff0c;如何选择一个高效、便捷且符合个人需求的笔记软件&#xff0c;成了许多人的难题。最近在逛…