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

华为开源自研AI框架昇思MindSpore应用案例:基于MindSpore框架的SGD优化器案例实现

SGD优化器基本原理讲解

随机梯度下降(SGD)是一种迭代方法,其背后基本思想最早可以追溯到1950年代的Robbins-Monro算法,用于优化可微分目标函数。

它可以被视为梯度下降优化的随机近似,因为它用实际梯度(从整个数据集计算)替换为实际梯度(从随机选择的数据子集计算)。特别是在高维优化问题中,这减少了非常高的计算负担,实现更快的迭代以换取更低的收敛速度。随机梯度下降已成为机器学习中重要的优化方法。

  

如果你对MindSpore感兴趣,可以关注昇思MindSpore社区

在这里插入图片描述

在这里插入图片描述

根据算法原理,用代码简单搭建了一个随机梯度下降算法的优化器:

 
import numpy as np
def SGD(data_x, data_y, alpha=0.1, maxepochs=10000,epsilon=1e-4):
    xMat = np.mat(data_x)
    yMat = np.mat(data_y)
    m, n = xMat.shape
    weights = np.ones((n, 1))  # 模型参数
    epochs_count = 0
    loss_list = []
    epochs_list = []
    while epochs_count < maxepochs:
        rand_i = np.random.randint(m)  # 随机取一个样本
        loss = cost(xMat,weights,yMat) #前一次迭代的损失值
        hypothesis = sigmoid(np.dot(xMat[rand_i,:],weights)) #预测值
        error = hypothesis -yMat[rand_i,:] #预测值与实际值误差
        grad = np.dot(xMat[rand_i,:].T,error) #损失函数的梯度
        weights = weights - alpha*grad #参数更新
        loss_new = cost(xMat,weights,yMat)#当前迭代的损失值
        print(loss_new)
        if abs(loss_new-loss)<epsilon:
            break
        loss_list.append(loss_new)
        epochs_list.append(epochs_count)
        epochs_count += 1
    print('迭代到第{}次,结束迭代!'.format(epochs_count))
    plt.plot(epochs_list,loss_list)
    plt.xlabel('epochs')
    plt.ylabel('loss')
    plt.show()
    return weights

 基于MindSpore框架源码的SGD优化方法讲解

def decay_weight(self, gradients):
    if self.exec_weight_decay:
        params = self._parameters
        weight_decay = self.get_weight_decay()
        if self.is_group:
            gradients = self.map_(F.partial(_apply_decay), weight_decay, self.decay_flags, params, gradients)
        else:
            gradients = self.map_(F.partial(_apply_decay, weight_decay), self.decay_flags, params, gradients)

    return gradients

def get_weight_decay(self):
    if self.dynamic_weight_decay:
        if self.is_group:
            weight_decay = ()
            for weight_decay_, flag_ in zip(self.weight_decay, self.dynamic_decay_flags):
                current_weight_decay = weight_decay_(self.global_step) if flag_ else weight_decay_
                weight_decay += (current_weight_decay,)
            return weight_decay
        return self.weight_decay(self.global_step)
    return self.weight_decay

SGD应用案例

以上介绍了SGD以及它的很多优化方法,但如何选择优化方法和对应的参数依然是一个问题。

本部分我们希望通过一个案例设计一组对比实验,演示如何在实践中使用SGD优化器。通过这个案例,我们希望能达成三个目的:一是能够快速入门MindSpore,并将其应用于实践;二是掌握MindSpore框架SGD优化器的使用方法;三是比较不同参数设置下SGD优化器算法的性能,探究SGD优化器参数设置问题。

应用案例介绍

 案例流程

本案例使用数据集Fashion MNIST训练lenet网络模型,中间调用MindSpore提供的SGD优化器API,并设置三组实验来对比SGD优化器不同参数的选择对模型训练带来的影响。三组实验学习率固定设为0.01。实验一为SGD不带任何优化参数,实验二为SGD+momentum,实验三为SGD+momentum+nesterov。momentum与nesterov在理论上都能加速网络训练。最后通过实验数据可视化分析,得出结论。

关于数据集

Fashion MNIST(服饰数据集)是经典MNIST数据集的简易替换,MNIST数据集包含手写数字(阿拉伯数字)的图像,两者图像格式及大小都相同。Fashion MNIST比常规 MNIST手写数据将更具挑战性。两者数据集都较小,主要适用于初学者学习或验证某个算法可否正常运行。他们是测试和调试代码的良好起点。

Fashion MNIST/服饰数据集包含70000张灰度图像,其中包含60,000个示例的训练集和10,000个示例的测试集,每个示例都是一个28x28灰度图像。

数据集文件路径如下:

./mnist/
├── test
│   ├── t10k-images-idx3-ubyte
│   └── t10k-labels-idx1-ubyte
└── train├── train-images-idx3-ubyte└── train-labels-idx1-ubyte

实验步骤

首先配置环境,要求MindSpore>=1.8.1,还需要安装mindvision和解决兼容性问题。如果使用Jupyter Notebook做本实验,完成后需要重启内核。

[ ]

 
!pip install mindvision
!pip uninstall opencv-python-headless-4.6.0.66
!pip install "opencv-python-headless<4.3"

导入需要的模块

[8]

 
from mindspore import ops
from mindspore import nn
import csv

由于mindvision支持几种经典数据集,其中就有FashionMnist。我们直接使用mindvision接口下载FashionMnist数据集,并且无需进行数据预处理。

[ ]

 
from mindvision.classification.dataset import FashionMnist
download_train = FashionMnist(path="./FashionMnist", split="train", batch_size=32, repeat_num=1, shuffle=True,
                         resize=32, download=True)
download_test = FashionMnist(path="./FashionMnist", split="test", batch_size=32, resize=32, download=True)
train_dataset = download_train.run()
test_dataset = download_test.run()

检查数据集结构

[10]

 
for image, label in train_dataset.create_tuple_iterator():
    print(f"Shape of image [N, C, H, W]: {image.shape} {image.dtype}")
    print(f"Shape of label: {label.shape} {label.dtype}")
    break
Shape of image [N, C, H, W]: (32, 1, 32, 32) Float32
Shape of label: (32,) Int32

使用LeNet网络,因为这是一个优化器算法比较案例,对网络没有特殊要求,这里推荐直接使用mindvision提供的接口。记得数据集为灰度图,通道数需要设为1。

[11]

 
from mindvision.classification.models import lenet
network = lenet(num_classes=10, num_channel=1, include_top=True)

创建训练函数和测试函数。对于测试函数,采用两个指标来评估模型质量:一是在测试集上的预测精度,二是在测试集上的平均损失。将这两个数据保存在csv文件中,方便后续处理。

[12]

 
from mindspore import ops
from mindspore import nn
# 定义训练函数
def train(model, dataset, loss_fn, optimizer):
    # Define forward function
    def forward_fn(data, label):
        logits = model(data)
        loss = loss_fn(logits, label)
        return loss, logits
    # Get gradient function
    grad_fn = ops.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)
    # Define function of one-step training
    def train_step(data, label):
        (loss, _), grads = grad_fn(data, label)
        loss = ops.depend(loss, optimizer(grads))
        return loss
    size = dataset.get_dataset_size()
    model.set_train()
    for batch, (data, label) in enumerate(dataset.create_tuple_iterator()):
        loss = train_step(data, label)
        if batch % 100 == 0:
            loss, current = loss.asnumpy(), batch
            print(f"loss: {loss:>7f}  [{current:>3d}/{size:>3d}]")
# 除训练外,我们定义测试函数,用来评估模型的性能。
def test(model, dataset, loss_fn, writer):
    num_batches = dataset.get_dataset_size()
    model.set_train(False)
    total, test_loss, correct = 0, 0, 0
    for data, label in dataset.create_tuple_iterator():
        pred = model(data)
        total += len(data)
        test_loss += loss_fn(pred, label).asnumpy()
        correct += (pred.argmax(1) == label).asnumpy().sum()
    test_loss /= num_batches
    correct /= total
    print(f"Test: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
    correct = round(correct * 100, 1)
    test_loss = round(test_loss,6)
    writer.writerow([correct, test_loss]) #将数据保存在对应的csv文件中

定义损失函数和优化器函数。损失函数使用交叉熵损失函数,优化器选择SGD,迭代次数为10,学习率固定设为0.01。在每次训练过后都将模型用测试集评估性能,来体现训练过程。

下面是实验一,使用纯粹的SGD优化器。

[13]

 
import csv
from mindvision.classification.models import lenet
from mindspore import nn
# 构建网络模型
network1 = lenet(num_classes=10, num_channel=1, include_top=True)
# 定义损失函数
net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
# 定义优化器函数
net_opt = nn.SGD(network1.trainable_params(), learning_rate=1e-2)
# 设置迭代次数
epochs = 10
csv_file1 = open('result/sgd1.csv', 'w', newline='') 
writer1 = csv.writer(csv_file1)
writer1.writerow(['Accuracy', 'Avg_loss'])
for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")
    train(network1, train_dataset, net_loss, net_opt)
    test(network1, test_dataset, net_loss, writer1)
csv_file1.close()
print("Done!")
Epoch 1
-------------------------------
loss: 2.302577  [  0/1875]
loss: 2.302847  [100/1875]
loss: 2.302751  [200/1875]
loss: 2.302980  [300/1875]
loss: 2.303654  [400/1875]
loss: 2.303366  [500/1875]
loss: 2.304052  [600/1875]
loss: 2.302124  [700/1875]
loss: 2.300979  [800/1875]
loss: 2.305120  [900/1875]
loss: 2.302595  [1000/1875]
loss: 2.302863  [1100/1875]
loss: 2.302272  [1200/1875]
loss: 2.302855  [1300/1875]
loss: 2.301332  [1400/1875]
loss: 2.302946  [1500/1875]
loss: 2.302062  [1600/1875]
loss: 2.301753  [1700/1875]
loss: 2.302556  [1800/1875]
Test: Accuracy: 10.0%, Avg loss: 2.302537 Epoch 2
-------------------------------
loss: 2.302315  [  0/1875]
loss: 2.302679  [100/1875]
loss: 2.303077  [200/1875]
loss: 2.302937  [300/1875]
loss: 2.303362  [400/1875]
loss: 2.303807  [500/1875]
loss: 2.301589  [600/1875]
loss: 2.301368  [700/1875]
loss: 2.299467  [800/1875]
loss: 2.304304  [900/1875]
loss: 2.303492  [1000/1875]
loss: 2.303529  [1100/1875]
loss: 2.304138  [1200/1875]
loss: 2.301667  [1300/1875]
loss: 2.301730  [1400/1875]
loss: 2.303048  [1500/1875]
loss: 2.303775  [1600/1875]
loss: 2.303029  [1700/1875]
loss: 2.302475  [1800/1875]
Test: Accuracy: 16.2%, Avg loss: 2.302400 Epoch 3
-------------------------------
loss: 2.301794  [  0/1875]
loss: 2.303500  [100/1875]
loss: 2.302805  [200/1875]
loss: 2.302227  [300/1875]
loss: 2.301216  [400/1875]
loss: 2.302775  [500/1875]
loss: 2.301936  [600/1875]
loss: 2.302594  [700/1875]
loss: 2.302720  [800/1875]
loss: 2.302242  [900/1875]
loss: 2.303227  [1000/1875]
loss: 2.301566  [1100/1875]
loss: 2.301122  [1200/1875]
loss: 2.301184  [1300/1875]
loss: 2.299739  [1400/1875]
loss: 2.302099  [1500/1875]
loss: 2.301378  [1600/1875]
loss: 2.299140  [1700/1875]
loss: 2.298317  [1800/1875]
Test: Accuracy: 19.9%, Avg loss: 2.299189 Epoch 4
-------------------------------
loss: 2.298693  [  0/1875]
loss: 2.298517  [100/1875]
loss: 2.295070  [200/1875]
loss: 2.287685  [300/1875]
loss: 2.273570  [400/1875]
loss: 2.171952  [500/1875]
loss: 1.555109  [600/1875]
loss: 1.315035  [700/1875]
loss: 1.290831  [800/1875]
loss: 0.957171  [900/1875]
loss: 0.683247  [1000/1875]
loss: 1.657022  [1100/1875]
loss: 0.885075  [1200/1875]
loss: 0.906517  [1300/1875]
loss: 0.904378  [1400/1875]
loss: 1.017345  [1500/1875]
loss: 1.311617  [1600/1875]
loss: 0.797807  [1700/1875]
loss: 0.899135  [1800/1875]
Test: Accuracy: 69.3%, Avg loss: 0.824970 Epoch 5
-------------------------------
loss: 0.632757  [  0/1875]
loss: 0.734659  [100/1875]
loss: 0.945924  [200/1875]
loss: 0.672319  [300/1875]
loss: 0.684902  [400/1875]
loss: 0.706946  [500/1875]
loss: 0.759072  [600/1875]
loss: 0.552457  [700/1875]
loss: 0.529598  [800/1875]
loss: 1.010510  [900/1875]
loss: 0.701660  [1000/1875]
loss: 0.749967  [1100/1875]
loss: 0.557507  [1200/1875]
loss: 0.663519  [1300/1875]
loss: 0.856946  [1400/1875]
loss: 0.672521  [1500/1875]
loss: 0.620852  [1600/1875]
loss: 0.940065  [1700/1875]
loss: 0.525178  [1800/1875]
Test: Accuracy: 74.8%, Avg loss: 0.673452 Epoch 6
-------------------------------
loss: 0.526541  [  0/1875]
loss: 0.551981  [100/1875]
loss: 0.437927  [200/1875]
loss: 0.536838  [300/1875]
loss: 0.612873  [400/1875]
loss: 0.663827  [500/1875]
loss: 0.462745  [600/1875]
loss: 0.553594  [700/1875]
loss: 0.411590  [800/1875]
loss: 0.748116  [900/1875]
loss: 0.510949  [1000/1875]
loss: 0.381978  [1100/1875]
loss: 0.571769  [1200/1875]
loss: 0.576415  [1300/1875]
loss: 0.674996  [1400/1875]
loss: 0.657864  [1500/1875]
loss: 0.638442  [1600/1875]
loss: 0.409129  [1700/1875]
loss: 0.637906  [1800/1875]
Test: Accuracy: 78.8%, Avg loss: 0.573736 Epoch 7
-------------------------------
loss: 0.303391  [  0/1875]
loss: 0.386003  [100/1875]
loss: 0.689905  [200/1875]
loss: 0.512580  [300/1875]
loss: 0.466622  [400/1875]
loss: 0.435113  [500/1875]
loss: 0.432267  [600/1875]
loss: 0.504910  [700/1875]
loss: 0.666079  [800/1875]
loss: 0.614079  [900/1875]
loss: 0.400944  [1000/1875]
loss: 0.448082  [1100/1875]
loss: 0.767068  [1200/1875]
loss: 0.498046  [1300/1875]
loss: 0.530967  [1400/1875]
loss: 0.754128  [1500/1875]
loss: 0.558144  [1600/1875]
loss: 0.258042  [1700/1875]
loss: 0.358890  [1800/1875]
Test: Accuracy: 81.6%, Avg loss: 0.510896 Epoch 8
-------------------------------
loss: 0.506675  [  0/1875]
loss: 0.753561  [100/1875]
loss: 0.468868  [200/1875]
loss: 0.422411  [300/1875]
loss: 0.396021  [400/1875]
loss: 0.393111  [500/1875]
loss: 0.963203  [600/1875]
loss: 0.572667  [700/1875]
loss: 0.288582  [800/1875]
loss: 0.419174  [900/1875]
loss: 0.356242  [1000/1875]
loss: 0.464459  [1100/1875]
loss: 0.501630  [1200/1875]
loss: 0.593385  [1300/1875]
loss: 0.398698  [1400/1875]
loss: 0.774741  [1500/1875]
loss: 0.300537  [1600/1875]
loss: 0.626626  [1700/1875]
loss: 0.468578  [1800/1875]
Test: Accuracy: 80.9%, Avg loss: 0.520291 Epoch 9
-------------------------------
loss: 0.393862  [  0/1875]
loss: 0.242075  [100/1875]
loss: 0.380720  [200/1875]
loss: 0.613354  [300/1875]
loss: 0.313823  [400/1875]
loss: 0.708381  [500/1875]
loss: 0.501862  [600/1875]
loss: 0.367467  [700/1875]
loss: 0.601890  [800/1875]
loss: 0.417870  [900/1875]
loss: 0.465760  [1000/1875]
loss: 0.626054  [1100/1875]
loss: 0.564844  [1200/1875]
loss: 0.439832  [1300/1875]
loss: 0.247064  [1400/1875]
loss: 0.210835  [1500/1875]
loss: 0.672299  [1600/1875]
loss: 0.483748  [1700/1875]
loss: 0.694968  [1800/1875]
Test: Accuracy: 83.5%, Avg loss: 0.455580 Epoch 10
-------------------------------
loss: 0.391544  [  0/1875]
loss: 0.305324  [100/1875]
loss: 0.416478  [200/1875]
loss: 0.437293  [300/1875]
loss: 0.253441  [400/1875]
loss: 0.500829  [500/1875]
loss: 0.511331  [600/1875]
loss: 0.390801  [700/1875]
loss: 0.466885  [800/1875]
loss: 0.345322  [900/1875]
loss: 0.454487  [1000/1875]
loss: 0.409122  [1100/1875]
loss: 0.191410  [1200/1875]
loss: 0.507366  [1300/1875]
loss: 0.580812  [1400/1875]
loss: 0.367076  [1500/1875]
loss: 0.314957  [1600/1875]
loss: 0.409756  [1700/1875]
loss: 0.368590  [1800/1875]
Test: Accuracy: 84.0%, Avg loss: 0.436875 Done!

实验二,控制其它变量不变,选择SGD优化器并使用参数momentum,设为0.9

[ ]

 
import csv
from mindvision.classification.models import lenet
from mindspore import nn
network2 = lenet(num_classes=10, num_channel=1, include_top=True)
net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
# 定义优化器函数
net_opt = nn.SGD(network2.trainable_params(), learning_rate=1e-2, momentum=0.9)
epochs = 10
csv_file2 = open('result/sgd2.csv', 'w', newline='')
writer2 = csv.writer(csv_file2)
writer2.writerow(['Accuracy', 'Avg_loss'])
for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")
    train(network2, train_dataset, net_loss, net_opt)
    test(network2, test_dataset, net_loss, writer2)
csv_file2.close()
print("Done!")

实验三,控制其它变量不变,选择SGD优化器并使用参数momentum,设为0.9,使用参数nesterov,设置为True

[ ]

 
import csv
from mindvision.classification.models import lenet
from mindspore import nn
network3 = lenet(num_classes=10, num_channel=1, include_top=True)
net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
# 定义优化器函数
net_opt = nn.SGD(network3.trainable_params(), learning_rate=1e-2, momentum=0.9, nesterov=True)
epochs = 10
csv_file3 = open('result/sgd3.csv', 'w', newline='')
writer3 = csv.writer(csv_file3)
writer3.writerow(['Accuracy', 'Avg_loss'])
for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")
    train(network3, train_dataset, net_loss, net_opt)
    test(network3, test_dataset, net_loss, writer3)
csv_file3.close()
print("Done!")

可视化分析

绘图

到此为止,我们获得了实验所有的数据,现在使用matplotlib对数据进行可视化分析。

首先对预测精度相关数据进行绘图

[ ]

 
import matplotlib.pyplot as plt
import numpy as np
f = open('result/sgd1.csv')  # 打开csv文件
reader = csv.reader(f)  # 读取csv文件
data1 = list(reader)  # csv数据转换为列表
f.close()
f = open('result/sgd2.csv')  # 打开csv文件
reader = csv.reader(f)  # 读取csv文件
data2 = list(reader)  # csv数据转换为列表
f.close()
f = open('result/sgd3.csv')  # 打开csv文件
reader = csv.reader(f)  # 读取csv文件
data3 = list(reader)  # csv数据转换为列表
f.close()
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y1 = list()
y2 = list()
y3 = list()
for i in range(1, 11):  # 从第二行开始读取
    y1.append(float(data1[i][0]))
    y2.append(float(data2[i][0]))
    y3.append(float(data2[i][0]))
plt.plot(x, y1, color='g', linestyle='-', label = 'SGD')  
plt.plot(x, y2, color='b', linestyle='-.', label = 'SGD+momentum')
plt.plot(x, y3, color='r', linestyle='--', label = 'SGD+momentum+nesterov')
plt.xlabel('epoch')
plt.ylabel('Accuracy')
plt.title('Accuracy graph')
plt.xlim((0, 10))
plt.ylim((0, 100))
my_y_ticks = np.arange(0, 100, 10)
plt.xticks(x)
plt.yticks(my_y_ticks)
plt.legend()
plt.savefig("sgd不同参数精确度对比图.png")
plt.show()  # 显示折线图

这是笔者训练的结果: 

对平均损失相关数据进行绘图

[ ]

 
import matplotlib.pyplot as plt
import numpy as np
f = open('result/sgd1.csv')  # 打开csv文件
reader = csv.reader(f)  # 读取csv文件
data1 = list(reader)  # csv数据转换为列表
f.close()
f = open('result/sgd2.csv')  # 打开csv文件
reader = csv.reader(f)  # 读取csv文件
data2 = list(reader)  # csv数据转换为列表
f.close()
f = open('result/sgd3.csv')  # 打开csv文件
reader = csv.reader(f)  # 读取csv文件
data3 = list(reader)  # csv数据转换为列表
f.close()
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y1 = list()
y2 = list()
y3 = list()
for i in range(1, 11):  # 从第二行开始读取
    y1.append(float(data1[i][1]))
    y2.append(float(data2[i][1]))
    y3.append(float(data2[i][1]))
plt.plot(x, y1, color='g', linestyle='-', label = 'SGD') 
plt.plot(x, y2, color='b', linestyle='-.', label = 'SGD+momentum')
plt.plot(x, y3, color='r', linestyle='--', label = 'SGD+momentum+nesterov')
plt.xlabel('epoch')
plt.ylabel('Avg_loss')
plt.title('Avg_loss graph')
plt.xlim((0, 10))
plt.ylim((0, 2.5))
my_y_ticks = np.arange(0, 3, 0.2)
plt.xticks(x)
plt.yticks(my_y_ticks)
plt.legend()
plt.savefig("sgd不同参数损失对比图.png")
plt.show()  # 显示折线图

这是笔者训练的结果: 

相关文章:

华为开源自研AI框架昇思MindSpore应用案例:基于MindSpore框架的SGD优化器案例实现

SGD优化器基本原理讲解 随机梯度下降&#xff08;SGD&#xff09;是一种迭代方法&#xff0c;其背后基本思想最早可以追溯到1950年代的Robbins-Monro算法&#xff0c;用于优化可微分目标函数。 它可以被视为梯度下降优化的随机近似&#xff0c;因为它用实际梯度&#xff08;从…...

μC/OS-Ⅱ源码学习(3)---事件模型

快速回顾 μC/OS-Ⅱ中的多任务 μC/OS-Ⅱ源码学习(1)---多任务系统的实现 μC/OS-Ⅱ源码学习(2)---多任务系统的实现(下) 本文开始&#xff0c;进入事件源码的学习。 事件模型 在一个多任务系统里&#xff0c;各个任务在系统的统筹下相继执行&#xff0c;由于执行速度极快&a…...

UnityShaderLab 实现黑白着色器效果

实现思路&#xff1a;取屏幕像素的RGB值&#xff0c;将三个通道的值相加&#xff0c;除以一个大于值使颜色值在0-1内&#xff0c;再乘上一个强度值调节黑白强度。 在URP中实现需要开启Opaque Texture ShaderGraph实现&#xff1a; ShaderLab实现&#xff1a; Shader "Bl…...

【Linux】文件管理必备知识和基本指令

【Linux】文件管理必备知识和基本指令 什么是操作系统什么是文件什么是路径01. ls 指令02. pwd命令03. cd 指令04. touch指令05.mkdir指令&#xff08;重要&#xff09;&#xff1a;06.rmdir指令 && rm 指令&#xff08;重要&#xff09;&#xff1a;rmdir指令rm指令 0…...

移远EC200A-CN的OPENCPU使用GO开发嵌入式程序TBOX

演示地址&#xff1a; http://134.175.123.194:8811 admin admin 演示视频&#xff1a; https://www.bilibili.com/video/BV196q2YQEDP 主要功能 WatchDog 1. 守护进程 2. OTA远程升级 TBOX 1. 数据采集、数据可视化、数据上报&#xff08;内置Modbus TCP/RTU/ASCII,GPS协…...

CSS 浮动定位

浮动定位 float : 浮动定位 left 左浮动right 右浮动 clear : 清除浮动 leftrightboth 浮动定位会导致 元素脱离正常文档流 、 对应的 父 元素 也可能会产生 高度坍塌 。 解决 父元素 高度坍塌的方案有&#xff1a; 1&#xff09; 父元素 添加 overflow , 值 为 除 visible 之…...

vmware vsphere5---部署vCSA(VMware vCenter Server)附带第二阶段安装报错解决方案

声明 因为这份文档我是边做边写的&#xff0c;遇到问题重新装了好几次所以IP会很乱 ESXI主机为192.168.20.10 VCSA为192.168.20.7&#xff0c;后台为192.168.20.7:5480 后期请自行对应&#xff0c;后面的192.168.20.57请对应192.168.20.7&#xff0c;或根据自己的来 第一阶段…...

Android Webview 详解

一 简介 一个基于webkit引擎、展现web页面的控件 Android 4.4前&#xff1a;Android Webview在低版本 & 高版本采用了不同的webkit版本的内核Android 4.4后&#xff1a;直接使用了Chrome内核 1.1 作用 在 Android 客户端上加载h5页面在本地 与 h5页面实现交互 & 调用…...

如何使用程序查询域名whois信息?

直接使用TCP协议向WHOIS服务器的43端口发送查询请求即可返回WHOIS信息。 一些国际域名(.COM/.NET/.CC等)需要继续向各注册商的WHOIS服务服务发送查询请求来获取详细信息。 大部分New gTLD来说&#xff0c;服务器是“whois.nic.[后缀]”&#xff0c;例如.red的WHOIS服务器为whoi…...

解决view-ui-plus 中表单验证不通过问题,select 组件开启multiple模式 总是提示错误,即使不验证也提示,有值也验证失败

&#x1f609; 你好呀&#xff0c;我是爱编程的Sherry&#xff0c;很高兴在这里遇见你&#xff01;我是一名拥有十多年开发经验的前端工程师。这一路走来&#xff0c;面对困难时也曾感到迷茫&#xff0c;凭借不懈的努力和坚持&#xff0c;重新找到了前进的方向。我的人生格言是…...

复杂系统如何架构?

一张图看懂整个后端系统架构 下图展示了整个后端系统架构&#xff0c;包括数据库、应用服务器、API网关等&#xff0c;展示了它们是如何协同工作的。 一些小贴士 CDN是现代互联网架构中不可或缺的一部分&#xff0c;特别是对于那些需要向全球用户提供高性能和高可用性服务的网站…...

leetcode 3224. 使差值相等的最少数组改动次数

题目链接&#xff1a;3224. 使差值相等的最少数组改动次数 题目&#xff1a; 给你一个长度为 n 的整数数组 nums &#xff0c;n 是偶数 &#xff0c;同时给你一个整数 k 。 你可以对数组进行一些操作。每次操作中&#xff0c;你可以将数组中任一元素替换为 0 到 k 之间的任一…...

C# 小案例(IT资产管理系统)

开发工具&#xff1a;visual studio 2022 语言&#xff1a;C# 数据库&#xff1a;Sql Server 2008 页面展示 一、登录 二、主窗体 三、用户管理 四、资产管理 五、关于 Java版地址&#xff1a;基于若依开发物品管理系统(springbootvue)_若依物品管理系统-CSDN博客 Python版…...

React第十四节useState使用详解差异

一、useState() Hook 使用 useState视图更新用法 1、写法&#xff1a; import { useState } from react const [name, setName] useState(Andy)利用数组解构写法&#xff0c; 第一个参数是自定义的属性&#xff0c;用于初始化时候渲染&#xff0c;如上面代码&#xff0c;初…...

ubuntu 安装 docker详细教程

1. 准备工作 1.1系统更新 sudo apt update sudo apt upgrade -y 1.2 检查系统版本 lsb_release -a 2.安装docker 2.1. 安装依赖 sudo apt install apt-transport-https ca-certificates curl software-properties-common 2.2 添加docker 官方GPG密钥 curl -fsSL https…...

图书管理系统|Java|SSM|JSP| 前后端分离

【一】可以提供远程部署安装&#xff0c;包扩环境 【二】提供软件相关的安装包 【三】如果需要提供java入门资料可咨询 【技术栈】 1⃣️&#xff1a;架构: B/S、MVC 2⃣️&#xff1a;系统环境&#xff1a;Windowsh/Mac 3⃣️&#xff1a;开发环境&#xff1a;IDEA、JDK1.8、M…...

Apache Echarts和POI

目录 Apache ECharts 介绍 入门 绘制一个简单的图表 Apache POI 介绍 通过POI创建Excel文件并且写入文件内容 通过POI读取Excel文件中的内容 导出Excel表格 Apache ECharts 介绍 Apache ECharts 是一款基于 Javascript 的数据可视化图表库&#xff0c;提供直观&#xf…...

ubuntu下的chattts 学习8(结束):长文本的语音转换优化及总结

代码 import ChatTTS import torch import numpy as np import torchaudio import re# 设置环境变量以避免内存碎片化 import os os.environ[PYTORCH_CUDA_ALLOC_CONF] expandable_segments:True# 使用 CPU 进行计算 device torch.device(cpu)chat ChatTTS.Chat() chat.loa…...

Luckysheet 实现 excel 多人在线协同编辑(全功能实现增强版)

前言 感谢大家对 Multi person online edit(多人在线编辑器) 项目的支持&#xff0c;mpoe 项目使用 quill、luckysheet、canvas-editor 实现的 md、excel、word 在线协同编辑&#xff0c;欢迎大家Fork 代码&#xff0c;多多 Start哦~ Multi person online edit 多人协同编辑器…...

最新VMware Workstation Pro领先的免费桌面虚拟化软件基于 x86 的 Windows 桌面虚拟化软件下载安装保姆级教程,直接下载,持续更新

目录 说明 安装程序下载 方法一&#xff1a;直接下载 方法二&#xff1a;官网下载 安装教程 说明 这几天重装电脑&#xff0c;想装VMware Workstation&#xff0c;搜了之后才发现它竟然对个人用户免费了&#xff0c;一个字&#xff1a;爽&#xff01;终于可以结束百度序列号…...

GitHub使用

太久不用GitHub发现自己又有些不会了&#xff0c;突发奇想为何不把每次看到的有指导意义的博客收录一下以便下次查阅呢 如何上传文件夹到GitHub上&#xff08;配图详解&#xff09;&#xff1f;_github上傳資料夾-CSDN博客 github上如何删除自己的仓库_github删除仓库-CSDN博…...

阿里云服务器Linux(centos)系统安装nginx1.20.2

阿里云服务器Linux(centos)系统安装nginx1.20.2 1.安装依赖包 一共要安装4种依赖&#xff08;基于c语言&#xff09; yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel2.下载nginx安装包并解压安装包 nginx官网下载&#xff1a;http://nginx.org/en/do…...

linux 用户名密码设置

安装linux时默认的密码最小长度是5个字节&#xff0c;但这并不够&#xff0c;要把它设为8个字节。修改最短密码长度需要编辑login.defs文件#vi /etc/login.defs PASS_MAX_DAYS 99999 #&#xff03;密码设置最长有效期&#xff08;默认值) PASS_MIN_DAYS 0 ##密…...

MySQL是否可以配合Keepalived实现高可用

MySQL是否可以配合Keepalived实现高可用 是的&#xff0c;MySQL 可以配合 Keepalived 实现高可用性。通常&#xff0c;使用 Keepalived 与 MySQL 配合的方式主要是通过配置 虚拟IP&#xff08;VIP&#xff09; 来实现主从数据库的自动切换&#xff0c;从而保证在主数据库宕机时…...

windows下 mysql开启 binlog日志

一、查看是否开启 binlog -- 方式一 show binary logs;-- 方式二 show VARIABLES like log_bin 说明没有开启 方式一 &#xff1a;you are not using binary logging 方式二&#xff1a;log_bin off 二、编辑 my.ini 配置文件 默认安装地点位于&#xff1a;C:\ProgramDat…...

59. 螺旋矩阵 II

59. 螺旋矩阵 II class Solution { public:vector<vector<int>> generateMatrix(int n) {// for(int i0;i<n;i){ 这样的遍历方式不对// for(int j 0;j<n;j){// generateMatrix[i][j] // }// } //初始化矩阵vector<vector<int&…...

XML 查看器:深入理解与高效使用

XML 查看器&#xff1a;深入理解与高效使用 XML&#xff08;可扩展标记语言&#xff09;是一种用于存储和传输数据的标记语言。它通过使用标签来定义数据结构&#xff0c;使得数据既易于人类阅读&#xff0c;也易于机器解析。在本文中&#xff0c;我们将探讨 XML 查看器的功能…...

JDBC学习

配置文件 application.yml spring: datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306/rbac?useUnicodetrue&characterEncodingutf-8&serverTimezoneUTC driver-class-name: com.mysql.jdbc.Driverrbac为我自己本地的数据库&…...

单元测试

junit5中五个方法为&#xff1a;Test、BeforeEach&#xff08;修饰实例方法&#xff0c;在测试方法开始之前执行&#xff09;、AfterEach&#xff08;修饰实例方法&#xff0c;在测试方法完成之后开始执行&#xff09;、BeforeAll&#xff08;修饰静态static方法&#xff0c;在…...

24/12/9 算法笔记<强化学习> PPO,DPPO

PPO是目前非常流行的增强学习算法&#xff0c;OpenAI把PPO作为目前baseline算法&#xff0c;首选PPO&#xff0c;可想而知&#xff0c;PPO可能不是最强的&#xff0c;但是是最广泛的。 PPO是基于AC架构&#xff0c;因为AC架构有一个好处&#xff0c;就是解决了连续动作空间的问…...

spring boot通过连接池的方式连接时序库IotDB

1、maven依赖 <dependency><groupId>org.apache.iotdb</groupId><artifactId>iotdb-session</artifactId><version>1.3.2</version></dependency>2、配置文件 iotdb:server:url: localhostport: 6667name: rootpwd: rootmax…...

maven多模块开发

目录 聚合 可选依赖 排除依赖 属性 打包 聚合 聚合就是将多个模块组成一个整体&#xff0c;进行项目构建。聚合工程&#xff08;也称为多模块项目&#xff09;是 Maven 的一种项目结构&#xff0c;它允许将一个大型项目拆分为多个较小的、更易于管理的子模块。每个子模块…...

Kubernetes Nginx-Ingress | 禁用HSTS/禁止重定向到https

目录 前言禁用HSTS禁止重定向到https关闭 HSTS 和设置 ssl-redirect 为 false 的区别 前言 客户请求经过ingress到服务后&#xff0c;默认加上了strict-transport-security&#xff0c;导致客户服务跨域请求失败&#xff0c;具体Response Headers信息如下&#xff1b; 分析 n…...

华为eNSP:VRRP

一、VRRP背景概述 在现代网络环境中&#xff0c;主机通常通过默认网关进行网络通信。当默认网关出现故障时&#xff0c;网络通信会中断&#xff0c;影响业务连续性和稳定性。为了提高网络的可靠性和冗余性&#xff0c;采用虚拟路由冗余协议&#xff08;VRRP&#xff09;是一种…...

linux 安装composer

下载composer curl -sS https://getcomposer.org/installer | php下载后设置环境变量&#xff0c;直接通过命令composer -v mv composer.phar /usr/local/bin/composer查看版本看是否安装成功 composer -v...

ESP32-S3模组上跑通ES8388(24)

接前一篇文章:ESP32-S3模组上跑通ES8388(23) 二、利用ESP-ADF操作ES8388 2. 详细解析 上一回解析完了es8388_init函数中的第8段代码,本回继续往下解析。为了便于理解和回顾,再次贴出es8388_init函数源码,在components\audio_hal\driver\es8388\es8388.c中,如下: ​ …...

类文件具有错误的版本 61.0, 应为 55.0 请删除该文件或确保该文件位于正确的类路径子目录中。

类文件具有错误的版本 61.0, 应为 55.0 请删除该文件或确保该文件位于正确的类路径子目录中。 这个错误表明你的项目尝试加载的 .class 文件&#xff08;编译好的 Java 类&#xff09;是用比你的运行环境支持更高版本的 Java 编译的。具体来说&#xff1a; 版本 61.0 对应 Ja…...

AI 的时代,新科技和新技术如何推动跨学科的整合?

在当前AI的发展中&#xff0c;我们面临的一个主要挑战就是融合的问题&#xff0c;这实际上不仅是技术上的融合&#xff0c;还有更深层次的哲学层面的思考。 或许在中国这方面的讨论较少&#xff0c;但在西方哲学和神学的语境中&#xff0c;探讨万物的根本和不同学科之间的联系…...

12.9-12.16学习周报

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract一、SNN与传统ANN的比较1.SNN概述2.SNN神经元和ANN的比较结构3.spikingjelly1.数据格式2.状态的保存和重置3.传播模式4.神经元 二、图数据库1.图数据库…...

CanFestival移植到STM32 F4芯片(基于HAL库)

本文讲述如何通过简单操作就可以把CanFestival库移植到STM32 F4芯片上&#xff0c;作为Slave设备。使用启明欣欣的工控板来做实验。 一 硬件连接 观察CAN报文需要专门的设备&#xff0c;本人从某宝上买了一个兼容PCAN的开源小板子&#xff0c;二十几块钱&#xff0c;通过USB接…...

构建安全的数据库环境:群晖NAS安装MySQL和phpMyAdmin详细步骤

文章目录 前言1. 安装MySQL2. 安装phpMyAdmin3. 修改User表4. 本地测试连接MySQL5. 安装cpolar内网穿透6. 配置MySQL公网访问地址7. 配置MySQL固定公网地址8. 配置phpMyAdmin公网地址9. 配置phpmyadmin固定公网地址 前言 本文将详细讲解如何在群晖NAS上安装MySQL及其数据库管理…...

相机(Camera)硬件组成详解

简介&#xff1a;个人学习分享&#xff0c;如有错误&#xff0c;欢迎批评指正。 写在前面&#xff1a;可以去B站观看一些相机原理的视频来配合学习&#xff0c;这里推荐&#xff1a;推荐1&#xff0c;推荐2&#xff0c;推荐3 相机&#xff08;Camera&#xff09;是一种复杂的光…...

【Linux———基础IO】

每一滴眼泪&#xff0c;每一次心碎&#xff0c;什么爱能无疚无悔.......................................................................... 文章目录 前言 一、【认识文件I/O】 1.1、【回顾C语言文件I/O】 1.2、【操作系统文件I/O】 1.2.1、【open函数】 1、【open函数的三…...

WebRTC服务质量(03)- RTCP协议

一、前言&#xff1a; RTCP&#xff08;RTP Control Protocol&#xff09;是一种控制协议&#xff0c;与RTP&#xff08;Real-time Transport Protocol&#xff09;一起用于实时通信中的控制和反馈。RTCP负责监控和调节实时媒体流。通过不断交换RTCP信息&#xff0c;WebRTC应用…...

[python SQLAlchemy数据库操作入门]-10.性能优化:提升 SQLAlchemy 在股票数据处理中的速度

哈喽,大家好,我是木头左! 当处理大量数据时,如股票数据,默认的ORM操作可能会显得效率低下。本文将探讨如何通过一些技巧和策略来优化SQLAlchemy ORM的性能,从而提升其在股票数据处理中的速度。 1. 选择合适的数据类型 在定义模型时,选择合适的数据类型对于性能至关重要…...

23种设计模式之中介者模式

目录 1. 简介2. 代码2.1 Mediator &#xff08;中介者接口&#xff09;2.2 ChatRoom &#xff08;具体中介者类&#xff09;2.3 User &#xff08;同事接口&#xff09;2.4 ChatUser &#xff08;具体同事类&#xff09;2.5 Test &#xff08;测试&#xff09;2.6 运行结果 3. …...

MySQL:GROUP_CONCAT分组合并

目录 一、概述二、用法三、分组去重 一、概述 GROUP_CONCAT函数要配合group by才能发挥作用&#xff0c;主要用于分组之后合并某一字段。 二、用法 SELECT GROUP_CONCAT(age) FROM tb_user GROUP BY banner;三、分组去重 SELECT GROUP_CONCAT(DISTINCT age) FROM tb_user GRO…...

递归方式渲染嵌套的菜单项

1. 递归组件 递归方式渲染嵌套的菜单项&#xff0c;这个是非常好的做法。为了避免在每个子菜单上都渲染一个新的 <ul> 标签&#xff0c;可以使用 v-if 来判断是否有子菜单&#xff0c;再决定是否渲染子菜单的部分。 2. 提高性能 对于递归渲染组件&#xff0c;Vue 可能…...

常用Vim操作

vimrc配置 ctags -R * 生成tags文件 set number set ts4 set sw4 set autoindent set cindent set tag~/tmp/log/help/tags 自动补全&#xff1a; ctrln&#xff1a;自动补全 输入&#xff1a; a&#xff1a;从当前文字后插入i&#xff1a;从当前文字前插入s: 删除当前字…...

spark3 sql优化:同一个表关联多次,优化方案

目录 1.合并查询2.使用 JOIN 条件的过滤优化3.使用 Map-side Join 或 Broadcast Join4.使用 Partitioning 和 Bucketing5.利用 DataFrame API 进行优化假设 A 和 B 已经加载为 DataFramePerform left joins with specific conditions6.使用缓存或持久化7.避免笛卡尔积总结 1.合…...