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

颠覆语言认知的革命!神经概率语言模型如何突破人类思维边界?

颠覆语言认知的革命!神经概率语言模型如何突破人类思维边界?

一、传统模型的世纪困境:当n-gram遇上"月光族难题"

令人震惊的案例:2012年Google语音识别系统将

用户说:“我要还信用卡”
系统识别:“我要环信用开”

三大困境解析

  1. 维度灾难:当n=3时,词表大小10万 → 需要存储10^15个组合
  2. 数据稀疏:"量子计算融资"在10亿语料库中出现0次
  3. 长程依赖:无法捕捉"虽然…但是…"的超距离关联

二、神经概率语言模型:NPLM

NPLM的结构包括3个主要部分:输⼊层、隐藏层和输出层。

输⼊层将词汇映射到连续的词向量空间,隐藏层通过⾮线性激活函数学习词与词之间的复杂关系,输出层通过softmax函数产⽣下⼀个单词的概率分布。

image-20250309184522370

数学之美
P ( w t ∣ w t − 1 , . . . , w t − n + 1 ) = s o f t m a x ( C ⋅ t a n h ⁡ ( W x + b ) ) P ( w t ∣ w t − 1 , . . . , w t − n + 1 ) = softmax ( C ⋅ tanh ⁡ ( W x + b ) ) P(wt∣wt−1,...,wt−n+1)=softmax(C⋅tanh⁡(Wx+b))P(w_t|w_{t-1},...,w_{t-n+1}) = \text{softmax}(C \cdot \tanh(Wx + b)) P(wtwt1,...,wtn+1)=softmax(Ctanh(Wx+b))P(wtwt1,...,wtn+1)=softmax(Ctanh(Wx+b))
其中:

  • C C C:词向量到输出的连接矩阵
  • W W W:上下文词向量组合矩阵
  • x x x:上下文词向量拼接

2.1 NPLM的实现

image-20250309184711801

2.1.1 建立语料库
# 构建一个非常简单的数据集
sentences = ["我 喜欢 玩具", "我 爱 爸爸", "我 讨厌 挨打"] 
# 将所有句子连接在一起,用空格分隔成多个词,再将重复的词去除,构建词汇表
word_list = list(set(" ".join(sentences).split())) 
# 创建一个字典,将每个词映射到一个唯一的索引
word_to_idx = {word: idx for idx, word in enumerate(word_list)} 
# 创建一个字典,将每个索引映射到对应的词
idx_to_word = {idx: word for idx, word in enumerate(word_list)} 
voc_size = len(word_list) # 计算词汇表的大小
print(' 词汇表:', word_to_idx) # 打印词汇到索引的映射字典
print(' 词汇表大小:', voc_size) # 打印词汇表大小
 词汇表: {'爸爸': 0, '讨厌': 1, '我': 2, '玩具': 3, '爱': 4, '喜欢': 5, '挨打': 6}词汇表大小: 7
2.1.2 生成NPLM训练数据
# 构建批处理数据
import torch # 导入 PyTorch 库
import random # 导入 random 库
batch_size = 2 # 每批数据的大小
def make_batch():input_batch = []  # 定义输入批处理列表target_batch = []  # 定义目标批处理列表selected_sentences = random.sample(sentences, batch_size) # 随机选择句子for sen in selected_sentences:  # 遍历每个句子word = sen.split()  # 用空格将句子分隔成多个词# 将除最后一个词以外的所有词的索引作为输入input = [word_to_idx[n] for n in word[:-1]]  # 创建输入数据# 将最后一个词的索引作为目标target = word_to_idx[word[-1]]  # 创建目标数据input_batch.append(input)  # 将输入添加到输入批处理列表target_batch.append(target)  # 将目标添加到目标批处理列表input_batch = torch.LongTensor(input_batch) # 将输入数据转换为张量target_batch = torch.LongTensor(target_batch) # 将目标数据转换为张量return input_batch, target_batch  # 返回输入批处理和目标批处理数据
input_batch, target_batch = make_batch() # 生成批处理数据
print(" 输入批处理数据:",input_batch)  # 打印输入批处理数据
# 将输入批处理数据中的每个索引值转换为对应的原始词
input_words = []
for input_idx in input_batch:input_words.append([idx_to_word[idx.item()] for idx in input_idx])
print(" 输入批处理数据对应的原始词:",input_words)
print(" 目标批处理数据:",target_batch) # 打印目标批处理数据
# 将目标批处理数据中的每个索引值转换为对应的原始词
target_words = [idx_to_word[idx.item()] for idx in target_batch]
print(" 目标批处理数据对应的原始词:",target_words)
 输入批处理数据: tensor([[2, 1], [2, 4]])输入批处理数据对应的原始词: [['我', '讨厌'], ['我', '爱']]目标批处理数据: tensor([6, 0])目标批处理数据对应的原始词: ['挨打', '爸爸']

batch_size = 2 # 每批数据的大小

image-20250310194259986

即为整理好数据集,及其对应的结果,接下来只等构建网络和训练

2.1.3 定义NPLM
import torch.nn as nn # 导入神经网络模块
# 定义神经概率语言模型(NPLM)
class NPLM(nn.Module):def __init__(self):super(NPLM, self).__init__() self.C = nn.Embedding(voc_size, embedding_size) # 定义一个词嵌入层# 第一个线性层,其输入大小为 n_step * embedding_size,输出大小为 n_hiddenself.linear1 = nn.Linear(n_step * embedding_size, n_hidden) # 第二个线性层,其输入大小为 n_hidden,输出大小为 voc_size,即词汇表大小self.linear2 = nn.Linear(n_hidden, voc_size) def forward(self, X):  # 定义前向传播过程# 输入数据 X 张量的形状为 [batch_size, n_step]X = self.C(X)  # 将 X 通过词嵌入层,形状变为 [batch_size, n_step, embedding_size]        X = X.view(-1, n_step * embedding_size) # 形状变为 [batch_size, n_step * embedding_size]# 通过第一个线性层并应用 ReLU 激活函数hidden = torch.tanh(self.linear1(X)) # hidden 张量形状为 [batch_size, n_hidden]# 通过第二个线性层得到输出 output = self.linear2(hidden) # output 形状为 [batch_size, voc_size]return output # 返回输出结果

image-20250310194659088

进一部的说明我们结合以下代码

2.1.4 实例化NPLM
n_step = 2 # 时间步数,表示每个输入序列的长度,也就是上下文长度 
n_hidden = 2 # 隐藏层大小
embedding_size = 2 # 词嵌入大小
model = NPLM() # 创建神经概率语言模型实例
print(' NPLM 模型结构:', model) # 打印模型的结构

输入数据[[1,3], [1,6]](对应句子片段[“我 爱”, “我 讨厌”])

处理流程

  1. 嵌入层转为形状 [2,2,2] 的张量
  2. 展平为 [2,4]
  3. 第一线性层压缩到 [2,2]
  4. 第二线性层扩展到 [2,7](每个样本对应7个词的概率)

image-20250310195024069

2.1.5 训练NPLM
import torch.optim as optim # 导入优化器模块
criterion = nn.CrossEntropyLoss() # 定义损失函数为交叉熵损失
optimizer = optim.Adam(model.parameters(), lr=0.1) # 定义优化器为 Adam,学习率为 0.1
# 训练模型
for epoch in range(5000): # 设置训练迭代次数optimizer.zero_grad() # 清除优化器的梯度input_batch, target_batch = make_batch() # 创建输入和目标批处理数据output = model(input_batch) # 将输入数据传入模型,得到输出结果loss = criterion(output, target_batch) # 计算损失值if (epoch + 1) % 1000 == 0: # 每 1000 次迭代,打印损失值print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))loss.backward() # 反向传播计算梯度optimizer.step() # 更新模型参数

是不是中一段训练的设定看着挺抽象,接下来举一个简单的栗子:

for epoch in range(5000):optimizer.zero_grad()          # 清空炒锅残留(重置梯度)input_batch, target = make_batch()  # 随机选菜谱(数据采样)output = model(input_batch)    # 学生试做菜品(前向传播)loss = criterion(output, target) # 老师试吃评分(计算损失)loss.backward()                # 分析哪里做错了(反向传播)optimizer.step()               # 根据建议改进(参数更新)
image-20250310195240344
2.1.6 用NPLM预测新词
# 进行预测
input_strs = [['我', '讨厌'], ['我', '喜欢']]  # 需要预测的输入序列
# 将输入序列转换为对应的索引
input_indices = [[word_to_idx[word] for word in seq] for seq in input_strs]
# 将输入序列的索引转换为张量
input_batch = torch.LongTensor(input_indices) 
# 对输入序列进行预测,取输出中概率最大的类别
predict = model(input_batch).data.max(1)[1]  
# 将预测结果的索引转换为对应的词
predict_strs = [idx_to_word[n.item()] for n in predict.squeeze()]  
for input_seq, pred in zip(input_strs, predict_strs):print(input_seq, '->', pred)  # 打印输入序列和预测结果
['我', '讨厌'] -> 挨打['我', '喜欢'] -> 玩具

image-20250310195543613

2.2 完整手撕

最开始的学习中容易对NPLM建立中纬度的变化中产生疑惑,接下来进行具体得分析。

image-20250310195740161

其结构可以拆分为一个三明治结构

输入词索引 → 嵌入层 → 全连接层1+激活 → 全连接层2 → 词汇概率分布

让我们用具体数值示例(假设参数如下)逐步解析:

voc_size = 7        # 词汇表大小(示例数据实际值)
n_step = 2          # 用前2个词预测第3个词
embedding_size = 2  # 词向量维度(示例设定)
n_hidden = 2        # 隐藏层维度(示例设定)

2.2.1 输入数据示例

假设输入批处理数据为:

input_batch = [[1,3], [1,6]]  # 对应句子片段:"我 爱"、"我 讨厌"
# 转换为张量后形状:[batch_size=2, n_step=2]

2.2.2 前向传播逐层分解

1. 嵌入层(Embedding Layer)
self.C = nn.Embedding(7, 2)  # 参数:7词→2维向量
X = self.C(input_batch)      # 输入:[2,2] → 输出:[2,2,2]

相当于把索引中的七个词转化为二维的向量,转化过程如下

计算过程

  • 每个词索引查表获取对应向量
# 假设嵌入矩阵(随机初始化示例):
[[0.1, 0.2],  # 索引0:'挨打'[0.3, 0.4],  # 索引1:'我'[0.5, 0.6],  # 索引2:'爸爸' [0.7, 0.8],  # 索引3:'爱'[0.9, 1.0],  # 索引4:'喜欢'[1.1, 1.2],  # 索引5:'玩具'[1.3, 1.4]   # 索引6:'讨厌'
]# 输入[[1,3], [1,6]]的嵌入结果:
[[[0.3,0.4], [0.7,0.8]],  # "我 爱"[[0.3,0.4], [1.3,1.4]]   # "我 讨厌"
]

数学本质
将离散的词索引映射为连续可训练的向量空间中的点,公式:
E = EmbeddingLookup ( X ) \mathbf{E} = \text{EmbeddingLookup}(\mathbf{X}) E=EmbeddingLookup(X)
其中 X ∈ Z b a t c h × n _ s t e p \mathbf{X} \in \mathbb{Z}^{batch×n\_step} XZbatch×n_step, E ∈ R b a t c h × n _ s t e p × e m b e d d i n g _ s i z e \mathbf{E} \in \mathbb{R}^{batch×n\_step×embedding\_size} ERbatch×n_step×embedding_size


2. 特征拼接(Flatten)
X = X.view(-1, n_step*embedding_size)  # [2,2,2] → [2,4]

具体变换

# 第一个样本:"我 爱"  
原始嵌入 → [0.3,0.4], [0.7,0.8]  
拼接后 → [0.3, 0.4, 0.7, 0.8]# 第二个样本:"我 讨厌"  
原始嵌入 → [0.3,0.4], [1.3,1.4]  
拼接后 → [0.3, 0.4, 1.3, 1.4]

技术意义
将序列的时序信息转换为空间特征,为全连接层提供固定长度的输入。


3. 第一全连接层(Feature Projection)
self.linear1 = nn.Linear(4, 2)  # 输入4维 → 输出2维
hidden = torch.tanh(self.linear1(X))  # [2,4] → [2,2]

参数示例
假设权重和偏置为(点乘):
W 1 = [ 0.1 − 0.2 0.3 0.4 − 0.5 0.6 0.7 − 0.8 ] , b 1 = [ 0.1 − 0.2 ] W_1 = \begin{bmatrix} 0.1 & -0.2 & 0.3 & 0.4 \\ -0.5 & 0.6 & 0.7 & -0.8 \end{bmatrix}, \quad b_1 = \begin{bmatrix} 0.1 \\ -0.2 \end{bmatrix} W1=[0.10.50.20.60.30.70.40.8],b1=[0.10.2]

计算演示

# 第一个样本计算:
[0.3, 0.4, 0.7, 0.8] × W1 + b1
= (0.3*0.1 + 0.4*(-0.2) + 0.7*0.3 + 0.8*0.4) + 0.1 = 0.54 → tanh(0.54)0.49  
= (0.3*(-0.5) + 0.4*0.6 + 0.7*0.7 + 0.8*(-0.8)) + (-0.2) = -0.56 → tanh(-0.56)-0.51
输出 → [0.49, -0.51]

数学表达式
h = tanh ⁡ ( X f l a t W 1 ⊤ + b 1 ) \mathbf{h} = \tanh(\mathbf{X}_{flat}W_1^\top + \mathbf{b}_1) h=tanh(XflatW1+b1)
其中 W 1 ∈ R n _ h i d d e n × ( n _ s t e p × e m b e d d i n g _ s i z e ) W_1 \in \mathbb{R}^{n\_hidden×(n\_step×embedding\_size)} W1Rn_hidden×(n_step×embedding_size)


4. 第二全连接层(Output Projection)
self.linear2 = nn.Linear(2,7)  # 2维→7分类
output = self.linear2(hidden)  # [2,2] → [2,7]

相当于将第一层的输入进行线性变换后(上下文特征的抽象提取),通过激活函数得出的结果分别再与第二层的参数进行线性变换(语义到词汇的概率映射),通过结果可以判断出哪一个词语为预测词的概率更大。

参数示例
假设:
W 2 = [ 0.2 − 0.3 0.4 0.1 − 0.5 0.6 0.7 − 0.8 − 0.9 0.2 1.0 0.3 0.1 − 0.4 ] , b 2 = [ 0.1 , 0.2 , − 0.3 , 0.4 , − 0.5 , 0.6 , − 0.7 ] W_2 = \begin{bmatrix} 0.2 & -0.3 \\ 0.4 & 0.1 \\ -0.5 & 0.6 \\ 0.7 & -0.8 \\ -0.9 & 0.2 \\ 1.0 & 0.3 \\ 0.1 & -0.4 \end{bmatrix}, \quad b_2 = [0.1, 0.2, -0.3, 0.4, -0.5, 0.6, -0.7] W2= 0.20.40.50.70.91.00.10.30.10.60.80.20.30.4 ,b2=[0.1,0.2,0.3,0.4,0.5,0.6,0.7]

计算演示

# 第一个样本隐藏值 [0.49, -0.51]
计算每个输出单元:
0.49*0.2 + (-0.51)*(-0.3) + 0.10.098 + 0.153 + 0.1 = 0.351 → 输出单元0  
0.49*0.4 + (-0.51)*0.1 + 0.20.196 - 0.051 + 0.2 = 0.345 → 输出单元1  
...以此类推所有7个单元

数学表达式
o = h W 2 ⊤ + b 2 \mathbf{o} = \mathbf{h}W_2^\top + \mathbf{b}_2 o=hW2+b2
其中 W 2 ∈ R v o c _ s i z e × n _ h i d d e n W_2 \in \mathbb{R}^{voc\_size×n\_hidden} W2Rvoc_size×n_hidden


2.2.3 输出结果解读

最终得到形状为 [batch_size, voc_size]未归一化概率(logits),例如:

output = [[0.35, 0.34, -1.2, 0.8, 2.1, -0.3, 0.5],  # 样本1:预测"喜欢"(索引4)概率最高[1.2, -0.5, 0.7, 0.3, -0.8, 0.9, 2.3]     # 样本2:预测"讨厌"(索引6)概率最高
]

要得到概率分布,需应用Softmax:

probs = torch.softmax(output, dim=1)
# probs ≈ [
#   [0.05, 0.05, 0.01, 0.10, 0.60, 0.09, 0.10], 
#   [0.15, 0.03, 0.08, 0.07, 0.02, 0.10, 0.55]
# ]

2.2.4 参数计算详解

1. 嵌入层参数

参数数 = v o c _ s i z e × e m b e d d i n g _ s i z e = 7 × 2 = 14 \text{参数数} = voc\_size × embedding\_size = 7×2 = 14 参数数=voc_size×embedding_size=7×2=14

2. 第一全连接层

参数数 = ( n _ s t e p × e m b e d d i n g _ s i z e ) × n _ h i d d e n + n _ h i d d e n = 4 × 2 + 2 = 10 \text{参数数} = (n\_step×embedding\_size) × n\_hidden + n\_hidden = 4×2 + 2 = 10 参数数=(n_step×embedding_size)×n_hidden+n_hidden=4×2+2=10

3. 第二全连接层

参数数 = n _ h i d d e n × v o c _ s i z e + v o c _ s i z e = 2 × 7 + 7 = 21 \text{参数数} = n\_hidden × voc\_size + voc\_size = 2×7 + 7 = 21 参数数=n_hidden×voc_size+voc_size=2×7+7=21

总参数:14 + 10 + 21 = 45个可训练参数

相关文章:

颠覆语言认知的革命!神经概率语言模型如何突破人类思维边界?

颠覆语言认知的革命!神经概率语言模型如何突破人类思维边界? 一、传统模型的世纪困境:当n-gram遇上"月光族难题" 令人震惊的案例:2012年Google语音识别系统将 用户说:“我要还信用卡” 系统识别&#xff…...

【实战ES】实战 Elasticsearch:快速上手与深度实践-5.1.1热点分片识别与均衡策略

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 5.1.1 Filebeat Logstash ES Kibana 全链路配置实1. 架构设计与组件选型1.1 技术栈对比分析1.2 硬件配置推荐 2. Filebeat 高级配置2.1 多输入源配置2.2 性能优化参数 3.…...

练习:关于静态路由,手工汇总,路由黑洞,缺省路由相关

这是题目,我已经画分好了网段,题目要求是这样的: 划分网段 我为什么一个网段划了6个可用IP(一个网段8个地址)呢,因为我刚开始吧环回接口理解成一个主机了,导致我认为两个环回主机在一个网段,其实每个网段只需要2个地址就可以完成这个练习,我懒得划了,就按第一张图的网段来吧…...

J6打卡——pytorch实现ResNeXt-50实现猴痘检测

🍨 本文为🔗365天深度学习训练营中的学习记录博客 🍖 原作者:K同学啊 1.检查GPU import torch import torch.nn as nn import torchvision.transforms as transforms import torchvision from torchvision import transforms, d…...

vue+dhtmlx-gantt 实现甘特图-快速入门【甘特图】

文章目录 一、前言二、使用说明2.1 引入依赖2.2 引入组件2.3 引入dhtmlx-gantt2.4 甘特图数据配置2.5 初始化配置 三、代码示例3.1 Vue2完整示例3.2 Vue3 完整示例 四、效果图 一、前言 dhtmlxGantt 是一款功能强大的甘特图组件,支持 Vue 3 集成。它提供了丰富的功…...

音视频入门基础:RTP专题(16)——RTP封装音频时,音频的有效载荷结构

一、引言 《RFC 3640》和《RFC 6416》分别定义了两种对MPEG-4流的RTP封包方式,这两个文档都可以从RFC官网下载: RFC Editor 本文主要对《RFC 3640》中的音频打包方式进行简介。《RFC 3640》总共有43页,本文下面所说的“页数”是指在pdf阅读…...

通领科技冲刺北交所

高质量增长奔赴产业新征程 日前,通领科技已正式启动在北交所的 IPO 进程,期望借助资本市场的力量,加速技术升级,推动全球化战略布局。这一举措不仅展现了中国汽车零部件企业的强大实力,也预示着行业转型升级的新突破。…...

超分之DeSRA

Desra: detect and delete the artifacts of gan-based real-world super-resolution models.DeSRA:检测并消除基于GAN的真实世界超分辨率模型中的伪影Xie L, Wang X, Chen X, et al.arXiv preprint arXiv:2307.02457, 2023. 摘要 背景: GAN-SR模型虽然…...

Ubuntu用户安装cpolar内网穿透

前言 Cpolar作为一款体积小巧却功能强大的内网穿透软件,不仅能够在多种环境和应用场景中发挥巨大作用,还能适应多种操作系统,应用最为广泛的Windows、Mac OS系统自不必多说,稍显小众的Linux、树莓派、群辉等也在起支持之列&#…...

小程序事件系统 —— 33 事件传参 - data-*自定义数据

事件传参:在触发事件时,将一些数据作为参数传递给事件处理函数的过程,就是事件传参; 在微信小程序中,我们经常会在组件上添加一些自定义数据,然后在事件处理函数中获取这些自定义数据,从而完成…...

【Java学习】包装类

面向对象系列九 包装类变量 一、装箱 1.实例化包装对象 2.静态缓存池 3.写法 二、拆箱 包装类变量 每个基本数据类型都有对应的基本类型的包装类变量,将基本数据类型通过对应的包装类对象载入着进入到类与对象面向对象体系 一、装箱 Integer.valueOf(int) —…...

中国自动化领域零部件研究报告

一、引言 1.1 研究背景与目的 随着科技的飞速发展,自动化技术已成为推动各行业转型升级的关键力量。中国自动化领域零部件行业在近年来取得了显著进展,市场规模持续扩大,技术水平不断提升。在政策支持与市场需求的双重驱动下,中…...

Neo4j 数据库备份

将包括系统数据库在内的所有数据库的最近备份存储在一个安全的位置是非常重要的。这确保了在发生数据丢失或损坏时,能够迅速恢复数据库到最近的状态,减少可能的业务影响。对于不同的数据库环境(开发、测试或生产),根据…...

【每日学点HarmonyOS Next知识】span问题、组件标识属性、属性动画回调、图文混排、相对布局问题

1、HarmonyOS 如果有两个span 第一个span放的是中文 第二个span超长 这时候 Ellipsis会展示异常? 如果有两个span 第一个span放的是中文 第二个span超长 这时候 Ellipsis会展示异常 设置断行规则.wordBreak(WordBreak.BREAK_ALL)即可。 参考连接:http…...

MySQL数据集成:高效数据同步与监控

MySQL数据集成案例分享:user-钉钉部门树-名称刷新 在企业信息系统中,数据的高效流动和准确同步是确保业务连续性和决策支持的重要环节。本文将聚焦于一个具体的系统对接集成案例——将MySQL中的数据集成到另一个MySQL数据库中,方案名称为“u…...

时序数据库TimescaleDB基本操作示例

好的&#xff01;以下是使用 TimescaleDB 的 Java 示例&#xff08;基于 JDBC&#xff0c;因为 TimescaleDB 是 PostgreSQL 的扩展&#xff0c;官方未提供独立的 Java SDK&#xff09;&#xff1a; 1. 添加依赖&#xff08;Maven&#xff09; <dependency><groupId&g…...

【VBA】WPS/PPT设置标题字体

通过VBA&#xff0c;配合左上角的快速访问工具栏&#xff0c;实现自动化调整 选中文本框的 字体位置、大小、颜色。 配合quicker更加便捷 Sub DisableAutoWrapAndFormat()Dim shp As Shape 检查是否选中了一个形状&#xff08;文本框&#xff09;If ActiveWindow.Selection.Typ…...

Python Flask 和数据库系统交互

Python Flask 和数据库系统交互 Python Flask 和数据库系统交互 Python Flask 和数据库系统交互 全栈网页应用程序需要结构化数据的持久性&#xff0c;因此使用数据库的知识和经验是网页开发的先决条件。Python 和Flask 可以与大多数SQL或无SQL数据库系统集成。Python本身附带…...

Qt:事件

目录 处理事件 鼠标事件 键盘事件 定时器事件 窗口事件 虽然 Qt 是跨平台的 C 开发框架&#xff0c;Qt 的很多能力其实是操作系统提供的 只不过 Qt 封装了系统的 API 事件 前面学习过信号槽&#xff1a; 用户进行的各种操作&#xff0c;就可能会产生出信号&#xff0c;可以…...

3个 Vue Scoped 的核心原理

大家好&#xff0c;我是大澈&#xff01;一个喜欢结交朋友、喜欢编程技术和科技前沿的老程序员&#x1f468;&#x1f3fb;‍&#x1f4bb;&#xff0c;关注我&#xff0c;科技未来或许我能帮到你&#xff01; 先用一句话概括 Vue Scoped 的核心原理&#xff1a;Vue 的 scoped…...

物联网IoT系列之MQTT协议基础知识

文章目录 物联网IoT系列之MQTT协议基础知识物联网IoT是什么&#xff1f;什么是MQTT&#xff1f;为什么说MQTT是适用于物联网的协议&#xff1f;MQTT工作原理核心组件核心机制 MQTT工作流程1. 建立连接2. 发布和订阅3. 消息确认4. 断开连接 MQTT工作流程图MQTT在物联网中的应用 …...

工程化与框架系列(26)--前端可视化开发

前端可视化开发 &#x1f4ca; 引言 前端可视化是现代Web应用中不可或缺的一部分&#xff0c;它能够以直观的方式展示复杂的数据和信息。本文将深入探讨前端可视化开发的关键技术和最佳实践&#xff0c;包括图表绘制、数据处理、动画效果等方面。 可视化技术概述 前端可视化…...

ubuntu 20.04 C++ 源码编译 cuda版本 opencv4.5.0

前提条件是安装好了cuda和cudnn 点击下载&#xff1a; opencv_contrib4.5.0 opencv 4.5.0 解压重命名后 进入opencv目录&#xff0c;创建build目录 “CUDA_ARCH_BIN ?” 这里要根据显卡查询一下,我的cuda是11&#xff0c;显卡1650&#xff0c;所以是7.5 查询方法1&#xff1…...

2025-03-07 学习记录--C/C++-PTA 习题8-5 使用函数实现字符串部分复制

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、题目描述 ⭐️ 二、代码&#xff08;C语言&#xff09;⭐️ #include <stdio.h> #define MAXN 20void strmcpy( char…...

【星云 Orbit•STM32F4】13. 探索定时器:基本定时器

【星云 Orbit•STM32F4】13. 探索定时器&#xff1a;基本定时器 七律 定时器 芯片之心精巧藏&#xff0c; 定时精准度量长。 初学莫畏千般难&#xff0c; 动手方知妙用强。 为读者提供完整代码&#xff0c;但不提供代码文件&#xff0c;也别做“三键”工程师。唯有自己动手&…...

江科大51单片机笔记【10】蜂鸣器(上)

一、蜂鸣器 1.原理 蜂鸣器是一种将电信号转换为声音信号的器件&#xff0c;常同来产生设备的按键音、报警音等提示信号蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器&#xff08;外观基本一样&#xff09;有源蜂鸣器&#xff1a;内部自带振荡源&#xff0c;将正负极接上直流…...

最新版本WebContext构造函数-避坑

import org.thymeleaf.context.IWebContext; import org.thymeleaf.context.WebContext; 当你想把页面信息全部获取出来存到redis缓存中使用时&#xff0c;SpringWebContext在Spring5中报错 SpringWebContext ctx new SpringWebContext(request, response,request.getServlet…...

Java基础系列:深入解析Object类与面向对象编程核心机制

目录 一、Object类&#xff1a;万物之源的方法解析 1. 核心方法全景图 2. 关键方法深度剖析 2.1 equals与hashCode的契约关系 2.2 clone方法的三重陷阱 2.3 finalize方法的死亡警告 二、面向对象三大支柱解析 1. 封装&#xff08;Encapsulation&#xff09;安全防线 2…...

Spring Boot API 项目中 HAProxy 与 Nginx 的选择与实践

在开发 Spring Boot 构建的 RESTful API 项目时&#xff0c;负载均衡和反向代理是提升性能与可用性的关键环节。HAProxy 和 Nginx 作为两种流行的工具&#xff0c;经常被用于流量分发&#xff0c;但它们各有侧重。究竟哪一个更适合你的 Spring Boot API 项目&#xff1f;本文将…...

C++ 数据结构详解及学习规划

C++数据结构详解及学习规划 一、C++常用数据结构详解与示例 以下是C++中核心数据结构的分类及具体实现示例: 1. 线性数据结构 a. 数组(Array) • 定义:存储固定大小、同类型元素的连续内存结构。 • 特点:快速随机访问(O(1)),但插入/删除效率低(O(n))。 • 应用场…...