目录

随机种子

内参的初始化

神经网络调参指南 

参数的分类

调参顺序

初始化参数

batchsize的选择

学习率调整

激活函数的选择

损失函数的选择 

模型架构中的参数

正则化系数

其他补充


随机种子

import torch
import torch.nn as nn# 定义简单的线性模型(无隐藏层)
# 输入2个纬度的数据,得到1个纬度的输出
class SimpleNet(nn.Module):def __init__(self):super(SimpleNet, self).__init__()# 线性层:2个输入特征,1个输出特征self.linear = nn.Linear(2, 1)def forward(self, x):# 前向传播:y = w1*x1 + w2*x2 + breturn self.linear(x)# 创建模型实例
model = SimpleNet()# 查看模型参数
print("模型参数:")
for name, param in model.named_parameters():print(f"{name}: {param.data}")

模型参数:

linear.weight: tensor([[0.4099, 0.5500]])

linear.bias: tensor([0.3018])

torch中很多场景都会存在随机数

        1. 权重、偏置的随机初始化
        2. 数据加载(shuffing打乱)与批次加载(随机批次加载)的随机化
        3. 数据增强的随机化(随机旋转、缩放、平移、裁剪等)
        4. 随机正则化dropout
        5. 优化器中的随机性

import torch
import numpy as np
import os
import random# 全局随机函数
def set_seed(seed=42, deterministic=True):"""设置全局随机种子,确保实验可重复性参数:seed: 随机种子值,默认为42deterministic: 是否启用确定性模式,默认为True"""# 设置Python的随机种子random.seed(seed) os.environ['PYTHONHASHSEED'] = str(seed) # 确保Python哈希函数的随机性一致,比如字典、集合等无序# 设置NumPy的随机种子np.random.seed(seed)# 设置PyTorch的随机种子torch.manual_seed(seed) # 设置CPU上的随机种子torch.cuda.manual_seed(seed) # 设置GPU上的随机种子torch.cuda.manual_seed_all(seed)  # 如果使用多GPU# 配置cuDNN以确保结果可重复if deterministic:torch.backends.cudnn.deterministic = Truetorch.backends.cudnn.benchmark = False# 设置随机种子
set_seed(42)

介绍一下这个随机函数的几个部分

        1. python的随机种子,需要确保random模块、以及一些无序数据结构的一致性
        2. numpy的随机种子,控制数组的随机性 
        3. torch的随机种子,控制张量的随机性,在cpu和gpu上均适用
        4. cuDNN(CUDA Deep Neural Network library,CUDA深度神经网络库)的随机性,针对cuda的优化算法的随机性

内参的初始化

我们都知道。神经网络的权重需要通过反向传播来实现更新,那么最开始肯定需要一个值才可以更新参数

那么最开始的值是什么样的呢?如果恰好它们就是那一组最佳的参数附近的数,那么训练的速度就会快很多

为了搞懂这个问题,帮助我们真正理解神经网络参数的本质,需要深入剖析一下,关注以下几个问题:

        1. 初始值的区间
        2. 初始值的分布
        3. 初始值是多少

先介绍一下神经网络的对称性 ---- 为什么神经元的初始值需要各不相同?

本质神经网络的每个神经元都是在做一件事,输入x -- 输出y的映射,假设激活函数是sigmoid

y=sigmoid(wx+b),其中w是连接到该神经元的权重矩阵,b是该神经元的偏置

如果所有神经元的权重和偏置都一样,

        1. 如果全都为0,那么所有神经元的输出都一致,无法区分不同特征;此时反向传播的时候梯度都一样,无法学习到特征,更新后的权重也完全一致。
        2. 如果不为0,同上

所以,无论初始值是否为0,相同的权重和偏置会导致神经元在训练的过程中始终保持同步。(因为神经网络的前向传播是导致权重的数学含义是完全对成的)具体表现为:

同一层的神经元相当于在做完全相同的计算,无论输入如何变化,它们的输出模式始终一致。例如:输入图像中不同位置的边缘特征,会被这些神经元以相同方式处理,无法学习到空间分布的差异。

所以需要随机初始化,让初始的神经元各不相同。即使初始化差异很小,但激活函数的非线性(梯度不同)会放大这种差异。随着训练进行,这种分歧会逐渐扩大,最终形成功能各异的神经元。

实际上,神经网络的初始权重通常设置在0的小范围内(如[-0.1, 0.1]或[-0.01, 0.01]),或通过特定分布(如正态分布、均匀分布)生成最小值,有很多好处

避免梯度消失 / 爆炸:以sigmoid函数为例,其导数在输入绝对值较大时趋于0(如|x|> 5时,导数≈0)。若初始权重过大,输入 x=w・input+b 可能导致激活函数进入 “饱和区”,反向传播时梯度接近 0,权重更新缓慢(梯度消失)。类比:若初始权重是 “大值”,相当于让神经元一开始就进入 “极端状态”,失去对输入变化的敏感度。

如果梯度相对较大,就可以让变化处于sigmoid函数的非饱和区

所以其实对于不同的激活函数 ,都有对应的饱和区和非饱和区,深层网络中,饱和区会使梯度在反向传播时逐层衰减,底层参数几乎无法更新;

 

注意:这里是wx后才会经过激活函数,是多个权重印象的结果,不是收到单个权重决定的,所以单个权重可以取负数,但是如果求和后仍然小于0,那么输出会为0

所以初始值一般不会太大,结合不同激活函数的特性,而且初始值一般是小的值。最终训练完毕可能就会出现大的差异,这样最开始让每个参数都是有用的,至于最后是不是某些参数归0(失去价值),那得看训练才知道。 

来观察一下pytorch默认初始化的权重

import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import numpy as np# 设置设备
device = torch.device("mps")# 定义极简CNN模型(仅1个卷积层+1个全连接层)
class SimpleCNN(nn.Module):def __init__(self):super(SimpleCNN, self).__init__()# 卷积层:输入3通道,输出16通道,卷积核3x3self.conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1)# 池化层:2x2窗口,尺寸减半self.pool = nn.MaxPool2d(kernel_size=2)# 全连接层:展平后连接到10个输出(对应10个类别)# 输入尺寸:16通道 × 16x16特征图 = 16×16×16=4096self.fc = nn.Linear(16 * 16 * 16, 10)def forward(self, x):# 卷积+池化x = self.pool(self.conv1(x))  # 输出尺寸: [batch, 16, 16, 16]# 展平x = x.view(-1, 16 * 16 * 16)  # 展平为: [batch, 4096]# 全连接x = self.fc(x)  # 输出尺寸: [batch, 10]return x# 初始化模型
model = SimpleCNN()
model = model.to(device)# 查看模型结构
print(model)# 查看初始权重统计信息
def print_weight_stats(model):# 卷积层conv_weights = model.conv1.weight.dataprint("\n卷积层 权重统计:")print(f"  均值: {conv_weights.mean().item():.6f}")print(f"  标准差: {conv_weights.std().item():.6f}")print(f"  理论标准差 (Kaiming): {np.sqrt(2/3):.6f}")  # 输入通道数为3# 全连接层fc_weights = model.fc.weight.dataprint("\n全连接层 权重统计:")print(f"  均值: {fc_weights.mean().item():.6f}")print(f"  标准差: {fc_weights.std().item():.6f}")print(f"  理论标准差 (Kaiming): {np.sqrt(2/(16*16*16)):.6f}")# 改进的可视化权重分布函数
def visualize_weights(model, layer_name, weights, save_path=None):plt.figure(figsize=(12, 5))# 权重直方图plt.subplot(1, 2, 1)plt.hist(weights.cpu().numpy().flatten(), bins=50)plt.title(f'{layer_name} 权重分布')plt.xlabel('权重值')plt.ylabel('频次')# 权重热图plt.subplot(1, 2, 2)if len(weights.shape) == 4:  # 卷积层权重 [out_channels, in_channels, kernel_size, kernel_size]# 只显示第一个输入通道的前10个滤波器w = weights[:10, 0].cpu().numpy()plt.imshow(w.reshape(-1, weights.shape[2]), cmap='viridis')else:  # 全连接层权重 [out_features, in_features]# 只显示前10个神经元的权重,重塑为更合理的矩形w = weights[:10].cpu().numpy()# 计算更合理的二维形状(尝试接近正方形)n_features = w.shape[1]side_length = int(np.sqrt(n_features))# 如果不能完美整除,添加零填充使能重塑if n_features % side_length != 0:new_size = (side_length + 1) * side_lengthw_padded = np.zeros((w.shape[0], new_size))w_padded[:, :n_features] = ww = w_padded# 重塑并显示plt.imshow(w.reshape(w.shape[0] * side_length, -1), cmap='viridis')plt.colorbar()plt.title(f'{layer_name} 权重热图')plt.tight_layout()if save_path:plt.savefig(f'{save_path}_{layer_name}.png')plt.show()# 打印权重统计
print_weight_stats(model)# 可视化各层权重
visualize_weights(model, "Conv1", model.conv1.weight.data, "initial_weights")
visualize_weights(model, "FC", model.fc.weight.data, "initial_weights")# 可视化偏置
plt.figure(figsize=(12, 5))# 卷积层偏置
conv_bias = model.conv1.bias.data
plt.subplot(1, 2, 1)
plt.bar(range(len(conv_bias)), conv_bias.cpu().numpy())
plt.title('卷积层 偏置')# 全连接层偏置
fc_bias = model.fc.bias.data
plt.subplot(1, 2, 2)
plt.bar(range(len(fc_bias)), fc_bias.cpu().numpy())
plt.title('全连接层 偏置')plt.tight_layout()
plt.savefig('biases_initial.png')
plt.show()print("\n偏置统计:")
print(f"卷积层偏置 均值: {conv_bias.mean().item():.6f}")
print(f"卷积层偏置 标准差: {conv_bias.std().item():.6f}")
print(f"全连接层偏置 均值: {fc_bias.mean().item():.6f}")
print(f"全连接层偏置 标准差: {fc_bias.std().item():.6f}")

SimpleCNN(

(conv1): Conv2d(3, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (fc): Linear(in_features=4096, out_features=10, bias=True) )
卷积层 权重统计:

        均值: -0.005068

        标准差: 0.109001

        理论标准差 (Kaiming): 0.816497

全连接层 权重统计:

        均值: -0.000031

        标准差: 0.009038

        理论标准差 (Kaiming): 0.022097

偏置统计:

卷积层偏置 均值: -0.031176

卷积层偏置 标准差: 0.086302

全连接层偏置 均值: 0.003063

全连接层偏置 标准差: 0.010418

那么我们监控权重图的目的是什么呢?

训练时,权重会碎反向传播迭代更新。通过权重分布图,能直观看到其初始化(如随机分布)到逐渐收敛、形成规律模式的动态变化,理解模型如何一步步“学习”特征。比如,卷积层权重初期杂乱,训练后可能聚焦于边缘、纹理等特定模式。

识别梯度异常:

        1. 梯度消失:若权重分布越来越集中在0附近,且更新幅度极小,可能是梯度消失,模型难学到有效特征(比如深层网络用Sigmoid激活易出现)。
        2. 梯度爆炸:权重值突然大幅震荡、超出合理范围(比如从[-0.1, 0.1]跳到[-10, 10]),要警惕梯度爆炸,可能让训练崩溃。

借助tensorboard可以看到训练过程中权重图的变化

神经网络调参指南 

大部分时候,由于光是固定超参数的情况下,训练完模型就已经很耗时了,所以正常而言,基本不会采用传统机器学习的那些超参数方法,网格、贝叶斯、optuna之类的。

参数的分类

参数 = 外餐(实例化的手动指定的)+内参,其中把外参定义为超参数,也就是不需要数据驱动的那些参数

通常可以把超参数分为3类:网络参数、优化参数、正则化参数。

        - 网络参数:包括网络层之间的交互方式(如相加、相乘或串接)、卷积核的数量和尺寸、网络层数(深度)和激活函数等。
        - 优化参数:一般指学习率、批样本数量、不同优化器的参及部分损失函数的可调参数。
        - 正则化参数:如权重衰减系数、丢弃比率(dropout)。

超参数调优的目的是优化模型,找到最优解与正则化之间的关系。网络模型优化的目的是找到全局最优解(或相对更好的局部最优解),而正则项则希望模型能更好地拟合到最优。两者虽然存在一定对立,但目标是一致的,即最小化期望风险。模型优化希望最小化经济风险,但容易过拟合,而正则项用来约束模型复杂度。因此如何平衡两者关系,得到最优或较优的解,就是超参数调整的目标。

调参顺序

调参遵循“先保证模型能训练(基础配置)→再提升性能(核心参数)→最后抑制过拟合(正则化)”的思路,类似“先建框架,再装修,最后修细节”。

之前主要都是停留在第一步,先跑起来,如果想要更进一步提高精度,才是这些调参指南。所以下面顺序建立在已经跑通的基础上。

        1. 参数初始化 ---- 有预训练的参数直接起飞
        2. batchsize ---- 测试下允许的最高值
        3. epoch ---- 这个不必多说,默认都是训练到收敛位置,可以采取早停策略
        4. 学习率与调度器 ---- 收益最高,因为鞍点太多了,模型越复杂鞍点越多
        5. 模型结构 ---- 消融实验或者对照实验
        6. 损失函数 ---- 选择比较少,试出来一个即可,高手可以自己构建
        7. 激活函数 ---- 选择同样较少
        8. 正则化参数 ---- 主要是dropout,等到过拟合了用,上述所有步骤都是为了让模型过拟合

这个调参顺序并不固定,而且也不是按照重要度来选择,是按照方便程度来选择,比如选择少的选完后,会减少后续实验的成本。

初始化参数

预训练参数是最好的参数初始化方法,在训练前先找找类似的论文有无预训练参数,其次是Xavir,尤其是小数据集的场景,多找论文找到预训练模型最好的做法。关于预训练参数,优先动深层的参数,因为浅层是通用的;其次是学习率要采用分阶段的策略。

如果从0开始训练的话,PyTorch默认用Kaiming初始化(适配ReLU)或Xavier初始化(适配Sigmoid/Tanh)。

batchsize的选择

当Batchsize太小的时候,模型每次更新学到的东西太少了,很可能白学了因为缺少全局思维,所以尽可能高点,16的倍数即可,越大越好。

学习率调整

学习率就是参数更新的步长,LR过大→不好收敛;LR过小→训练停滞(陷入局部最优)

一般最开始用adam快速收敛,然后sgd收尾,一般精度会高一点;只能选一个就adam配合调度器使用。比如CosineAnnealingLR余弦退火调度器、StepLR固定步长衰减调度器,比如经典的搭配就是Adam + ReduceLROnPlateau,SGD + CosineAnnealing,或者Adam→SGD + StepLR。

比如最开始随便选了做了一组,后面为了刷精度就可以考虑选择更精细化的策略了

激活函数的选择

视情况而定,一般默认relu或其变体,如leaky relu,再或者用tanh。只有二分类任务最后输出层用sigmoid,多分类任务用softmax,其他全部用relu即可。此外特殊场景下,比如GELU(适配Transform)

损失函数的选择 

大部分我们目前接触的任务都是单个损失函数构成的,正常选择即可

分类任务:

        1. 交叉熵损失函数Cross-Entropy Loss -- 多分类场景
        2. 二元交叉熵损失函数Binary Cross-Entropy Loss -- 二分类场景
        3. Focal Loss -- 类别不平衡场景

注意点:

        - CrossEntropyLoss内置Softmax,输入应为原始logits(非概率)
        - BCEWithLogitsLoss内置Sigmoid,输入应为原始logits
        - 若评价指标为准确率,用交叉熵损失;若为F1分数,考虑Focal Loss或自定义损失。

回归任务:

        1. 均方误差MSE    
        2. 绝对误差MAE 这个也要根据场景和数据特点来选,不同损失收到异常值的影响程度不同

此外,还有一些序列任务的损失、生成任务的损失等等

后面还会遇到一个任务重有多个损失函数构成,比如加权成一个大的损失函数,就需要注意到二者的权重配比还有数量级的差异

模型架构中的参数

比如卷积核尺寸等,一般就是7*7、5*5、3*3这种奇数构成,最开始不要用太过分的下采样即可。

神经元的参数,直接用 Kaiming 初始化(适配 ReLU,PyTorch 默认)或 Xavier 初始化(适配 Sigmoid/Tanh)。

正则化系数

dropout一般控制在0.2-0.5之间,这里说个小技巧,先追求过拟合后追求泛化性。也就是说先把模型做到过拟合,然后在慢慢增加正则化程度。

正则化中,如果train的loss可以很低,但是val的loss还是很高,则说明泛化能力不够,优先让模型过拟合,再考虑加大正则化提高泛化能力,可以分模块来dropout,可以确定具体是哪部分参数导致过拟合,这里还有一个小技巧是引入残差链接后再利用dropout

L2权重衰减这个在优化器中就有,也算是正则化。

其他补充

对于复杂的项目,尽可能直接对着别人的已经跑通的源码来改。

在调参过程中可以监控tensorboard来关注训练过程。

无论怎么调参,提升的都是相对较小,优先考虑数据+特征工程做文章。

@浙大疏锦行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/87702.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/87702.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/87702.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET9 实现斐波那契数列(FibonacciSequence)性能测试

在 .NET 平台上实现 斐波那契数列 并使用 BenchmarkDotNet 进行性能测试&#xff0c;是评估不同算法实现方式性能表现的一种高效且标准化的方法。通过该方式&#xff0c;可以对比递归、迭代、记忆化递归以及结合高性能优化技术&#xff08;如 Span<T>、Memory<T> 和…

三、docker软件安装:gitlab,nexus,mysql8,redis,nacos,nginx

目录 1.gitlab安装 2.nexus安装 (1)下载启动 (2)设置中央仓库远程地址 (3)配置maven的settings.xml 3.mysql8安装 4.redis安装 5.nacos安装 6.nginx安装 1.gitlab安装 #创建目录 cd /usr/local/ mkdir docker cd docker/ mkdir gitlab_docker cd gitlab_docker…

【与AI+】SAP WEBGUI集成开发与SAP INTERNET服务的关系

前言&#xff1a;这是我的水水专栏第五篇文章&#xff0c;这个专栏呢&#xff0c;是放一些我向AI提问的问题&#xff0c;以及AI的回答。因为感觉真的好方便哈哈哈~ 我不是很确定我的专栏文章内容是否涉及版权&#xff0c;以及也不确定这些整合过的文字是否涉嫌抄袭&#xff0c…

浅谈几种js设计模式

JavaScript设计模式是开发中常用的一种解决方案&#xff0c;它们帮助开发者以一种更结构化、更易维护的方式编写代码。本文将深入介绍几种常见的JavaScript设计模式&#xff0c;包括单例模式、工厂模式、观察者模式和策略模式。 一、单例模式&#xff08;Singleton Pattern&am…

手写 Vue 中虚拟 DOM 到真实 DOM 的完整过程

目录 一、虚拟 DOM 的核心概念 二、虚拟 DOM 到真实 DOM 的流程 三、手写虚拟 DOM 到真实 DOM 的实现 1. 定义虚拟 DOM 的结构&#xff08;VNode&#xff09; 2. 创建虚拟 DOM 转真实 DOM 的函数 3. 挂载虚拟 DOM 到页面 4. 更新虚拟 DOM 的过程&#xff08;Diff 算法简化…

jmm--volatile

指令重排基础概念 在现代处理器和编译器为了提高程序执行效率&#xff0c;会对指令进行优化&#xff0c;其中一种优化方式就是指令重排序。在单线程环境下&#xff0c;指令重排序不会影响最终执行结果&#xff0c;因为处理器和编译器会保证重排序后的执行结果与按照代码顺序执行…

【硬件开发】滤波电容的选择:原理、计算与多电压值应用实践

滤波电容的选择&#xff1a;原理、计算与多电压值应用实践 1. 引言 在现代电子系统中&#xff0c;稳定的电源供应是保证电路可靠运行的基础。然而&#xff0c;电源线上往往不可避免地存在各种噪声和纹波&#xff0c;这些干扰可能源自电源本身&#xff08;如整流后的脉动直流&…

【seismic unix数据生成-unif2】

Seismic Unix简介 Seismic Unix&#xff08;SU&#xff09;是由科罗拉多矿业学院&#xff08;Colorado School of Mines&#xff09;开发的开源地震数据处理软件包&#xff0c;专为地震勘探数据分析和研究设计。它提供了一系列命令行工具&#xff0c;支持从数据加载、处理到可…

【逆向思考 并集查找】P2391 白雪皑皑|省选-

本文涉及知识点 C并集查找 P2391 白雪皑皑 题目背景 “柴门闻犬吠&#xff0c;风雪夜归人”&#xff0c;冬天&#xff0c;不期而至。千里冰封&#xff0c;万里雪飘。空中刮起了鸭毛大雪。雪花纷纷&#xff0c;降落人间。 美能量星球&#xff08;pty 在 spore 上的一个殖民地…

一文讲清楚React中setState的使用方法和机制

文章目录 一文讲清楚React中setState的使用方法和机制1. setState是什么2. setState方法详解2.1 setState参数详解2.2 setState同步异步问题2.2.1 setState异步更新2.2.2 setState同步更新 一文讲清楚React中setState的使用方法和机制 1. setState是什么 React中&#xff0c;…

01_软件卓越之道:功能性与需求满足

引言 在软件的世界里&#xff0c;功能性是产品与用户之间的第一桥梁。一个软件即使拥有华丽的界面和极致的性能&#xff0c;如果不能解决用户的核心需求&#xff0c;也终将被市场淘汰。本文将深入探讨如何确保软件的功能性与用户需求完美契合。 1. 需求理解&#xff1a;从模糊…

StarRocks × Tableau 连接器完整使用指南 | 高效数据分析从连接开始

一、导语&#xff1a;为什么选择 StarRocks Tableau 连接器&#xff1f; 在当今数据驱动的商业环境中&#xff0c;企业不仅需要一个能够处理海量数据的高性能分析数据库&#xff0c;还需要一个直观、强大的可视化工具来解读数据背后的故事。StarRocks 作为新一代极速全场景 MP…

基于 SpringBoot+VueJS 助农生鲜销售系统设计与实现7000字论文实现

摘要本论文设计并实现了一个基于 SpringBoot 和 VueJS 的助农生鲜销售系统。系统采用前后端分离架构&#xff0c;前端使用 VueJS 框架实现用户界面&#xff0c;后端使用 SpringBoot 框架构建服务&#xff0c;通过 MyBatis 实现数据持久化。系统实现了农产品展示、在线购物、订单…

Pytest 测试发现机制详解:自动识别测试函数与模块

概述 在编写自动化测试时,如何让 Pytest 自动找到你的测试代码 是一个非常基础但重要的问题。Pytest 通过其强大的 测试发现(Test Discovery)机制,能够自动扫描项目目录、识别测试模块和测试函数,从而大大简化了测试流程。 本文将为你详细讲解 Pytest 的测试发现机制,包…

MySQL 时间日期函数

时间日期类型 MySQL中主要支持以下几种时间日期类型&#xff1a; DATE - 日期类型 格式&#xff1a;YYYY-MM-DD范围&#xff1a;1000-01-01 到 9999-12-31示例&#xff1a;2023-05-20 TIME - 时间类型 格式&#xff1a;HH:MM:SS范围&#xff1a;-838:59:59 到 838:59:59示例&…

408第三季part2 - 计算机网络 - 物理层

理解 这里有8个波形&#xff0c;每个波形代表一个马原&#xff0c;一个马原代表多个比特&#xff0c;这里3个比特 求波特率就直接2W 求比特率就要乘log2V 这块记两公式就行&#xff0c;一个下面一个上面 题目 4个相位加4种幅度就是有16种波形 这里无噪声就是奈奎斯特定理 这…

iOS 集成RN Installing glog (0.3.5)报错的解决方案

在集成执行RN bundle exec pod install 命令到Installing glog (0.3.5)时报错,报错信息如下: Installing glog (0.3.5) [!] /bin/bash -c set -e #!/bin/bash # Copyright (c) Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license …

【进阶篇-消息队列】——MQTT协议如何支持海量的在线IoT设备

目录 一、什么是IoT二、MQTT 和其他消息队列的传输协议有什么不同三、如何选择 MQTT 产品四、MQTT 集群如何支持海量在线的 IoT 设备五、总结本文来源:极客时间vip课程笔记 一、什么是IoT IoT,也就是物联网,物联网这个词儿,它的含义还不那么直观,但你看它的英文:IoT,也就…

Chat Model API

聊天模型API为开发人员提供了将人工智能聊天完成功能集成到应用程序中的能力。它利用预训练的语言模型&#xff0c;如GPT&#xff08;生成预训练转换器&#xff09;&#xff0c;以自然语言对用户输入生成类似人类的响应。 API通常通过向人工智能模型发送提示或部分对话来工作&…

【黑群晖】自组硬件/旧电脑nas改造(三)——使用Jellyfin创建家庭影音库

一、打开套件中心安装Jellyfin套件 如果找不到Jellyfin套件&#xff0c;需要手动添加三方套件源&#xff1a; 《群晖NAS必学技能&#xff1a;一键解锁三方套件源&#xff0c;PT下载影音播放全搞定&#xff01;》 二、配置Jellyfin 访问http://群晖IP:8096 进入Jellyfin初始化界…