2024Datawhale AI夏令营---基于术语词典干预的机器翻译挑战赛--学习笔记

news/2024/9/2 13:04:38/ 标签: 人工智能, 机器翻译, 学习

#Datawhale #NLP

1.背景介绍:

        机器翻译(Machine Translation,简称MT)是自然语言处理领域的一个重要分支,其目标是将一种语言的文本自动转换为另一种语言的文本机器翻译的发展可以追溯到20世纪50年代,经历了从基于规则的方法、统计方法到深度学习方法的演变过程。

        当前,机器翻译正朝着更加智能化和个性化方向发展。一方面,结合上下文理解、情感分析等技术,提高翻译的准确性和自然度;另一方面,通过用户反馈和个性化学习,提供更加符合用户需求的翻译服务。同时,跨语言信息检索、多模态翻译等新兴领域也正在成为研究热点。

        总的来说,机器翻译的发展历程是从规则驱动到数据驱动,再到智能驱动的过程,反映了自然语言处理技术的进步和应用需求的变化

2.数据集简介:

        基于术语词典干预的机器翻译挑战赛选择以英文为源语言,中文为目标语言的机器翻译。本次大赛除英文到中文的双语数据,还提供英中对照的术语词典。参赛队伍需要基于提供的训练数据样本从多语言机器翻译模型的构建与训练,并基于测试集以及术语词典,提供最终的翻译结果

赛题数据划分:

  • 训练集:双语数据 - 中英14万余双语句对

  • 开发集:英中1000双语句对

  • 测试集:英中1000双语句对

  • 术语词典:英中2226条

  • 训练集(training set)用于运行你的学习算法。

  • 开发集(development set)用于调整参数,选择特征,以及对学习算法作出其它决定。有时也称为留出交叉验证集(hold-out cross validation set)

  • 测试集(test set)用于评估算法的性能,但不会据此改变学习算法或参数。

下面是每日任务打卡以及学习笔记:

task1:了解机器翻译 & 理解赛题

跑通baseline并上传数据:

baseline主要分为三个板块:模型训练,模型推理(验证集),模型推理(测试集)

模型训练:

值得注意的是,这里其实用的jupternotebook写的代码,就是一块一块的,一块定义一个函数并且写上notebook笔记注释,在最后一块写上if name主函数调用运行即可,运行的时候切记要将所有的代码块从头到尾一个个运行一遍,才能运行主函数,否则前面的代码编译器未编译,主函数里面调用的函数识别不出来。

这里我是图方便,全部合在一起了,到时候直接运行就好,和jupyter那个要从头到尾跑一遍代码块一样的道理,这就是python的特质,没有什么引入接口函数,必须要从头到尾来一遍才能读进去。(maybe)

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
from torchtext.data.utils import get_tokenizer
from collections import Counter
import random
from torch.utils.data import Subset, DataLoader
import time# 定义数据集类
# 修改TranslationDataset类以处理术语
class TranslationDataset(Dataset):def __init__(self, filename, terminology):self.data = []with open(filename, 'r', encoding='utf-8') as f:for line in f:en, zh = line.strip().split('\t')self.data.append((en, zh))self.terminology = terminology# 创建词汇表,注意这里需要确保术语词典中的词也被包含在词汇表中self.en_tokenizer = get_tokenizer('basic_english')self.zh_tokenizer = list  # 使用字符级分词en_vocab = Counter(self.terminology.keys())  # 确保术语在词汇表中zh_vocab = Counter()for en, zh in self.data:en_vocab.update(self.en_tokenizer(en))zh_vocab.update(self.zh_tokenizer(zh))# 添加术语到词汇表self.en_vocab = ['<pad>', '<sos>', '<eos>'] + list(self.terminology.keys()) + [word for word, _ in en_vocab.most_common(10000)]self.zh_vocab = ['<pad>', '<sos>', '<eos>'] + [word for word, _ in zh_vocab.most_common(10000)]self.en_word2idx = {word: idx for idx, word in enumerate(self.en_vocab)}self.zh_word2idx = {word: idx for idx, word in enumerate(self.zh_vocab)}def __len__(self):return len(self.data)def __getitem__(self, idx):en, zh = self.data[idx]en_tensor = torch.tensor([self.en_word2idx.get(word, self.en_word2idx['<sos>']) for word in self.en_tokenizer(en)] + [self.en_word2idx['<eos>']])zh_tensor = torch.tensor([self.zh_word2idx.get(word, self.zh_word2idx['<sos>']) for word in self.zh_tokenizer(zh)] + [self.zh_word2idx['<eos>']])return en_tensor, zh_tensordef collate_fn(batch):en_batch, zh_batch = [], []for en_item, zh_item in batch:en_batch.append(en_item)zh_batch.append(zh_item)# 对英文和中文序列分别进行填充en_batch = nn.utils.rnn.pad_sequence(en_batch, padding_value=0, batch_first=True)zh_batch = nn.utils.rnn.pad_sequence(zh_batch, padding_value=0, batch_first=True)return en_batch, zh_batchclass Encoder(nn.Module):def __init__(self, input_dim, emb_dim, hid_dim, n_layers, dropout):super().__init__()self.embedding = nn.Embedding(input_dim, emb_dim)self.rnn = nn.GRU(emb_dim, hid_dim, n_layers, dropout=dropout, batch_first=True)self.dropout = nn.Dropout(dropout)def forward(self, src):# src shape: [batch_size, src_len]embedded = self.dropout(self.embedding(src))# embedded shape: [batch_size, src_len, emb_dim]outputs, hidden = self.rnn(embedded)# outputs shape: [batch_size, src_len, hid_dim]# hidden shape: [n_layers, batch_size, hid_dim]return outputs, hiddenclass Decoder(nn.Module):def __init__(self, output_dim, emb_dim, hid_dim, n_layers, dropout):super().__init__()self.output_dim = output_dimself.embedding = nn.Embedding(output_dim, emb_dim)self.rnn = nn.GRU(emb_dim, hid_dim, n_layers, dropout=dropout, batch_first=True)self.fc_out = nn.Linear(hid_dim, output_dim)self.dropout = nn.Dropout(dropout)def forward(self, input, hidden):# input shape: [batch_size, 1]# hidden shape: [n_layers, batch_size, hid_dim]embedded = self.dropout(self.embedding(input))# embedded shape: [batch_size, 1, emb_dim]output, hidden = self.rnn(embedded, hidden)# output shape: [batch_size, 1, hid_dim]# hidden shape: [n_layers, batch_size, hid_dim]prediction = self.fc_out(output.squeeze(1))# prediction shape: [batch_size, output_dim]return prediction, hiddenclass Seq2Seq(nn.Module):def __init__(self, encoder, decoder, device):super().__init__()self.encoder = encoderself.decoder = decoderself.device = devicedef forward(self, src, trg, teacher_forcing_ratio=0.5):# src shape: [batch_size, src_len]# trg shape: [batch_size, trg_len]batch_size = src.shape[0]trg_len = trg.shape[1]trg_vocab_size = self.decoder.output_dimoutputs = torch.zeros(batch_size, trg_len, trg_vocab_size).to(self.device)_, hidden = self.encoder(src)input = trg[:, 0].unsqueeze(1)  # Start tokenfor t in range(1, trg_len):output, hidden = self.decoder(input, hidden)outputs[:, t, :] = outputteacher_force = random.random() < teacher_forcing_ratiotop1 = output.argmax(1)input = trg[:, t].unsqueeze(1) if teacher_force else top1.unsqueeze(1)return outputs# 新增术语词典加载部分
def load_terminology_dictionary(dict_file):terminology = {}with open(dict_file, 'r', encoding='utf-8') as f:for line in f:en_term, ch_term = line.strip().split('\t')terminology[en_term] = ch_termreturn terminologydef train(model, iterator, optimizer, criterion, clip):model.train()epoch_loss = 0for i, (src, trg) in enumerate(iterator):src, trg = src.to(device), trg.to(device)optimizer.zero_grad()output = model(src, trg)output_dim = output.shape[-1]output = output[:, 1:].contiguous().view(-1, output_dim)trg = trg[:, 1:].contiguous().view(-1)loss = criterion(output, trg)loss.backward()torch.nn.utils.clip_grad_norm_(model.parameters(), clip)optimizer.step()epoch_loss += loss.item()return epoch_loss / len(iterator)# 主函数
if __name__ == '__main__':start_time = time.time()  # 开始计时device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')#terminology = load_terminology_dictionary('../dataset/en-zh.dic')terminology = load_terminology_dictionary('E:/2024年项目资料/2024Datawhale AI夏令营---基于术语词典干预的机器翻译挑战赛/dataset/en-zh.dic')# 加载数据dataset = TranslationDataset('E:/2024年项目资料/2024Datawhale AI夏令营---基于术语词典干预的机器翻译挑战赛/dataset/train.txt',terminology = terminology)# 选择数据集的前N个样本进行训练N = 1000  #int(len(dataset) * 1)  # 或者你可以设置为数据集大小的一定比例,如 int(len(dataset) * 0.1)subset_indices = list(range(N))subset_dataset = Subset(dataset, subset_indices)train_loader = DataLoader(subset_dataset, batch_size=32, shuffle=True, collate_fn=collate_fn)# 定义模型参数INPUT_DIM = len(dataset.en_vocab)OUTPUT_DIM = len(dataset.zh_vocab)ENC_EMB_DIM = 256DEC_EMB_DIM = 256HID_DIM = 512N_LAYERS = 2ENC_DROPOUT = 0.5DEC_DROPOUT = 0.5# 初始化模型enc = Encoder(INPUT_DIM, ENC_EMB_DIM, HID_DIM, N_LAYERS, ENC_DROPOUT)dec = Decoder(OUTPUT_DIM, DEC_EMB_DIM, HID_DIM, N_LAYERS, DEC_DROPOUT)model = Seq2Seq(enc, dec, device).to(device)# 定义优化器和损失函数optimizer = optim.Adam(model.parameters())criterion = nn.CrossEntropyLoss(ignore_index=dataset.zh_word2idx['<pad>'])# 训练模型N_EPOCHS = 10CLIP = 1for epoch in range(N_EPOCHS):train_loss = train(model, train_loader, optimizer, criterion, CLIP)print(f'Epoch: {epoch+1:02} | Train Loss: {train_loss:.3f}')# 在训练循环结束后保存模型torch.save(model.state_dict(), 'E:/2024年项目资料/2024Datawhale AI夏令营---基于术语词典干预的机器翻译挑战赛/model/translation_model_GRU.pth')end_time = time.time()  # 结束计时# 计算并打印运行时间elapsed_time_minute = (end_time - start_time)/60print(f"Total running time: {elapsed_time_minute:.2f} minutes")

直接运行主函数: 

结果如下:这里我是按默认的参数只跑了10个epoch,训练了1000对中英翻译对,效果其实是会很差的。

模型推理(验证集): 

这里是用验证集先对模型进行一次评测,大家都懂验证集是用来干嘛的,就是拿来给模型调参的,这里只是一个演示,跑通了后面会发挥其作用用于调参。

import torch
from sacrebleu.metrics import BLEU
from typing import List# 假设我们已经定义了TranslationDataset, Encoder, Decoder, Seq2Seq类def load_sentences(file_path: str) -> list[str]:with open(file_path, 'r', encoding='utf-8') as f:return [line.strip() for line in f]# 更新translate_sentence函数以考虑术语词典
def translate_sentence(sentence: str, model: Seq2Seq, dataset: TranslationDataset, terminology, device: torch.device, max_length: int = 50):model.eval()tokens = dataset.en_tokenizer(sentence)tensor = torch.LongTensor([dataset.en_word2idx.get(token, dataset.en_word2idx['<sos>']) for token in tokens]).unsqueeze(0).to(device)  # [1, seq_len]with torch.no_grad():_, hidden = model.encoder(tensor)translated_tokens = []input_token = torch.LongTensor([[dataset.zh_word2idx['<sos>']]]).to(device)  # [1, 1]for _ in range(max_length):output, hidden = model.decoder(input_token, hidden)top_token = output.argmax(1)translated_token = dataset.zh_vocab[top_token.item()]if translated_token == '<eos>':break# 如果翻译的词在术语词典中,则使用术语词典中的词if translated_token in terminology.values():for en_term, ch_term in terminology.items():if translated_token == ch_term:translated_token = en_termbreaktranslated_tokens.append(translated_token)input_token = top_token.unsqueeze(1)  # [1, 1]return ''.join(translated_tokens)def evaluate_bleu(model: Seq2Seq, dataset: TranslationDataset, src_file: str, ref_file: str, terminology,device: torch.device):model.eval()src_sentences = load_sentences(src_file)ref_sentences = load_sentences(ref_file)translated_sentences = []for src in src_sentences:translated = translate_sentence(src, model, dataset, terminology, device)translated_sentences.append(translated)bleu = BLEU()score = bleu.corpus_score(translated_sentences, [ref_sentences])return score# 主函数
if __name__ == '__main__':device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')# 加载术语词典terminology = load_terminology_dictionary('E:/2024年项目资料/2024Datawhale AI夏令营---基于术语词典干预的机器翻译挑战赛/dataset/en-zh.dic')# 创建数据集实例时传递术语词典dataset = TranslationDataset('E:/2024年项目资料/2024Datawhale AI夏令营---基于术语词典干预的机器翻译挑战赛/dataset/train.txt', terminology)# 定义模型参数INPUT_DIM = len(dataset.en_vocab)OUTPUT_DIM = len(dataset.zh_vocab)ENC_EMB_DIM = 256DEC_EMB_DIM = 256HID_DIM = 512N_LAYERS = 2ENC_DROPOUT = 0.5DEC_DROPOUT = 0.5# 初始化模型enc = Encoder(INPUT_DIM, ENC_EMB_DIM, HID_DIM, N_LAYERS, ENC_DROPOUT)dec = Decoder(OUTPUT_DIM, DEC_EMB_DIM, HID_DIM, N_LAYERS, DEC_DROPOUT)model = Seq2Seq(enc, dec, device).to(device)# 加载训练好的模型model.load_state_dict(torch.load('E:/2024年项目资料/2024Datawhale AI夏令营---基于术语词典干预的机器翻译挑战赛/model/translation_model_GRU.pth'))# 评估BLEU分数bleu_score = evaluate_bleu(model, dataset, 'E:/2024年项目资料/2024Datawhale AI夏令营---基于术语词典干预的机器翻译挑战赛/dataset/dev_en.txt', 'E:/2024年项目资料/2024Datawhale AI夏令营---基于术语词典干预的机器翻译挑战赛/dataset/dev_zh.txt', terminology = terminology,device = device)print(f'BLEU-4 score: {bleu_score.score:.2f}')

这里验证集用的评分 指标是自动评价指标 BLEU-4 ,具体工具使用 sacrebleu开源版本

什么是 BLEU-4 ?下面简单的做一个介绍

   BLEU,全称为Bilingual Evaluation Understudy(双语评估替换),是一种对生成语句进行评估的指标。BLEU 评分是由Kishore Papineni等人2002年的论文《BLEU: a Method for Automatic Evaluation of Machine Translation》中提出的。

        在机器翻译领域,BLEU(Bilingual Evaluation Understudy)是一种常用的自动评价指标,用于衡量计算机生成的翻译与一组参考译文之间的相似度。这个指标特别关注 n-grams(连续的n个词)的精确匹配,可以被认为是对翻译准确性和流利度的一种统计估计。计算BLEU分数时,首先会统计生成文本中n-grams的频率,然后将这些频率与参考文本中的n-grams进行比较。如果生成的翻译中包含的n-grams与参考译文中出现的相同,则认为是匹配的。最终的BLEU分数是一个介于0到1之间的数值,其中1表示与参考译文完美匹配,而0则表示完全没有匹配。

        BLEU-4 特别指的是在计算时考虑四元组(即连续四个词)的匹配情况。

BLEU 评估指标的特点:

  • 优点:计算速度快、计算成本低、容易理解、与具体语言无关、和人类给的评估高度相关。

  • 缺点:不考虑语言表达(语法)上的准确性;测评精度会受常用词的干扰;短译句的测评精度有时会较高;没有考虑同义词或相似表达的情况,可能会导致合理翻译被否定。

        除翻译之外,BLEU评分结合深度学习方法可应用于其他的语言生成问题,例如:语言生成、图片标题生成、文本摘要、语音识别。

运行主函数,结果如下:

嘿嘿,直接是0,哈哈哈,效果确实很差

模型推理(测试集): 

下面就是正式的将我们的模型训练后,再经过验证集的调参之后,用于正式的测试啦

def inference(model: Seq2Seq, dataset: TranslationDataset, src_file: str, save_dir:str, terminology, device: torch.device):model.eval()src_sentences = load_sentences(src_file)translated_sentences = []for src in src_sentences:translated = translate_sentence(src, model, dataset, terminology, device)#print(translated)translated_sentences.append(translated)#print(translated_sentences)# 将列表元素连接成一个字符串,每个元素后换行text = '\n'.join(translated_sentences)# 打开一个文件,如果不存在则创建,'w'表示写模式with open(save_dir, 'w', encoding='utf-8') as f:# 将字符串写入文件f.write(text)#return translated_sentences# 主函数
if __name__ == '__main__':device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')# 加载术语词典terminology = load_terminology_dictionary('E:/2024年项目资料/2024Datawhale AI夏令营---基于术语词典干预的机器翻译挑战赛/dataset/en-zh.dic')# 加载数据集和模型dataset = TranslationDataset('E:/2024年项目资料/2024Datawhale AI夏令营---基于术语词典干预的机器翻译挑战赛/dataset/train.txt',terminology = terminology)# 定义模型参数INPUT_DIM = len(dataset.en_vocab)OUTPUT_DIM = len(dataset.zh_vocab)ENC_EMB_DIM = 256DEC_EMB_DIM = 256HID_DIM = 512N_LAYERS = 2ENC_DROPOUT = 0.5DEC_DROPOUT = 0.5# 初始化模型enc = Encoder(INPUT_DIM, ENC_EMB_DIM, HID_DIM, N_LAYERS, ENC_DROPOUT)dec = Decoder(OUTPUT_DIM, DEC_EMB_DIM, HID_DIM, N_LAYERS, DEC_DROPOUT)model = Seq2Seq(enc, dec, device).to(device)# 加载训练好的模型model.load_state_dict(torch.load('E:/2024年项目资料/2024Datawhale AI夏令营---基于术语词典干预的机器翻译挑战赛/model/translation_model_GRU.pth'))save_dir = 'E:/2024年项目资料/2024Datawhale AI夏令营---基于术语词典干预的机器翻译挑战赛/dataset/submit.txt'inference(model, dataset, src_file="E:/2024年项目资料/2024Datawhale AI夏令营---基于术语词典干预的机器翻译挑战赛/dataset/test_en.txt", save_dir = save_dir, terminology = terminology, device = device)print(f"翻译完成!文件已保存到{save_dir}")

test-data已经准备好了,这里就是将模型用于测试集进行推理吧,不能叫评测,结果如下:

额 这结果确实是意料之中的差啊哈哈哈哈,没事没事,这相当于让你看10遍一个1000对中英翻译,就能学会英语翻译另外1000个句子一样哈哈哈,impossible

 

并将推理结果提交至这里打分就好:

2024 iFLYTEK A.I.开发者大赛-讯飞开放平台 (xfyun.cn)

这样task1的baseline就跑通啦,后面就是更加细致的了解代码和赛题,进行各方面的优化架构和代码,疯狂上分!

task2:从baseline代码详解入门深度学习


http://www.ppmy.cn/news/1475740.html

相关文章

RABBITMQ的本地测试证书生成脚本

由于小程序要求必须访问wss的接口&#xff0c;因此需要将测试环境也切换到https&#xff0c;看了下官方的文档 RabbitMQ Web STOMP Plugin | RabbitMQ里面有这个信息 然后敲打GPT一阵子&#xff0c;把要求输入几个来回&#xff0c;得到这样一个脚本&#xff1a; generate_cer…

C语言 ——— 调试的时候如何查看当前程序的变量信息

目录 调试前/后的调试窗口 ​编辑 调试窗口 --- 监视 调试窗口 --- 内存 调试窗口 --- 调用堆栈 调试前/后的调试窗口 调试前的调试窗口&#xff1a; 调试前的调试窗口是没有显示的&#xff0c;只有在调试的时候才会有相对应的调试窗口 调试后的调试窗口&#xff1a…

Git的命令使用与IDEA内置git图形化的使用

Git 简介 Git 是分布式版本控制系统&#xff0c;它可以帮助开发人员跟踪和管理代码的更改。Git 可以记录代码的历史记录&#xff0c;并允许您在不同版本之间切换。 通过历史记录可以查看&#xff1a; 进行了哪些更改&#xff1f;谁进行了更改&#xff1f;何时进行了更改&#…

ARM架构(一)—— ARMV8V9基础概念

目录 1.ARMCore的时间线2.ARM术语小结2.1 A64和arrch642.2ARM架构现在的5个系列2.3 微架构2.4 PE2.5 Banked2.6 ARM文档术语2.7 IMPLEMENTATION DEFINFD 和 DEPRECATED2.8 EL1t和EL1h 3 ARMv7的软件架构4 安全状态切换模型4.1 Secure state和Non-secure state介绍 5 Interproce…

深入理解I/O模型

目录 一、I/O 模型简介 二、I/O 模型 2.1 同步阻塞 I/O 2.2 同步非阻塞I/O 2.3 I/O多路复用 2.4 异步I/O 2.5 信号驱动 I/O 三、总结 一、I/O 模型简介 所谓的 I/O 就是计算机内存与外部设备之间拷贝数据数据的过程。有 5 中 I/O 模型&#xff0c;分别是同步阻塞 I/O、同步…

细说MCU用定时器控制ADC采样频率的实现方法

目录 一、工程依赖的硬件及背景 二、设计目的 三、 建立工程 1.选择时钟源和Debug模式 2.配置系统时钟和ADC时钟 3.配置串口 4.配置ADC 5.设置TIM3 6.设置TIM4 7.配置中断 8.GPIO 四、代码修改 1.重新定义ADC回调函数 2.在主程序中编写数据发送代码 3.使能ADC和…

云端日历同步大师:iCloud让工作与生活井井有条

云端日历同步大师&#xff1a;iCloud让工作与生活井井有条 在快节奏的现代生活中&#xff0c;无论是工作还是个人生活&#xff0c;我们都需要一个可靠的日历应用来帮助我们管理日常事务和重要事件。iCloud作为苹果公司提供的云服务&#xff0c;其日历应用&#xff08;Apple Ca…

PyMuPDF 包读取pdf文档时,span里的flags属性代表什么

在 PyMuPDF&#xff08;也称为 fitz&#xff09;库中&#xff0c;flags 属性表示文本的格式化信息。flags 是一个整数&#xff0c;它包含了不同位&#xff08;bits&#xff09;的标志&#xff0c;每个位代表文本的一种属性。这些标志位可以组合在一起表示复杂的文本格式。 具体…

【学习笔记】无人机(UAV)在3GPP系统中的增强支持(三)-机上无线电接入节点无人机

引言 本文是3GPP TR 22.829 V17.1.0技术报告&#xff0c;专注于无人机&#xff08;UAV&#xff09;在3GPP系统中的增强支持。文章提出了多个无人机应用场景&#xff0c;分析了相应的能力要求&#xff0c;并建议了新的服务级别要求和关键性能指标&#xff08;KPIs&#xff09;。…

记一次使用vue连接rabbitMq

连接rabbitMq需要使用stompjsnpm i stompjs 下下面是连接代码 import Stomp from stompjsonConnected(frame) {// 绑定交换机exchange_pushmsg是交换机的名字rk_pushmsg是绑定的路由keyvar exchange this.rabbitMqexchange || queue.device.zzzz// 创建随机队列用上面的路由k…

神经网络替代密度泛函理论!清华研究组发布通用材料模型 DeepH,实现超精准预测

在材料设计中&#xff0c;了解其电子结构与性质是预测材料性能、发现新材料、优化材料性能的关键。过去&#xff0c;业界广泛使用密度泛函理论 (DFT) 来研究材料电子结构和性质&#xff0c;其实质是将电子密度作为分子&#xff08;原子&#xff09;基态中所有信息的载体&#x…

【Python】sklearn教程

1. sklearn库介绍 sklearn是 Python 中一个非常重要的机器学习库&#xff0c;全称为scikit-learn。它是基于Python语言的机器学习工具&#xff0c;提供了一系列简单高效的机器学习算法。sklearn库通常与NumPy和SciPy库一起使用&#xff0c;用于数据预处理、特征选择、模型训练…

无人机之遥控器分类篇

一、传统遥控器 传统无人机遥控器一般包括开关键、遥控天线等基础装置。但是会随着无人机具体的应用和功能而开发不同的按键。它的信号稳定性远超对比其他遥控&#xff0c;而且遥控距离也更远&#xff08;一般遥控范围在100米或以上&#xff09;传统遥控器对于初学者来说比较难…

/EtherCATInfo/Descriptions/Devices/Device/SubDevice/@Hideable

SubDevice/Hideable 属性 /EtherCATInfo/Descriptions/Devices/Device/SubDevice/Hideable 出现次数&#xff1a;可选 (0…1)数据类型&#xff1a;布尔值 该属性仅应在列出所有子设备的主设备的 ESI 文件中使用。该属性表示配置工具是否可以隐藏相应的子设备。只有不需要配置…

PXE、Kickstart和cobbler

一.系统装机 1.1 三种引导方式 启动操作系统 1.硬盘 2.光驱(u盘) 3.网络启动 pxe 1.2 系统安装过程 1.加载boot loader: Boot Loader 是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设 备、建立内存空间的映射图,从而将系统的软硬…

多旋翼无人机挂载多功能抛投器技术详解

多旋翼无人机&#xff0c;作为一种具有高效、灵活、稳定等特性的无人驾驶飞行器&#xff0c;在现代社会的多个领域得到了广泛应用。其中&#xff0c;挂载多功能抛投器技术&#xff0c;使得无人机在物资投送、救援等任务中发挥出更加重要的作用。以下将详细介绍多旋翼无人机挂载…

搜索引擎算法工程师,在query理解方面,都有哪些方面的工作

一、什么是query理解&#xff1f; 通俗来讲&#xff0c;就是query整形。又可以理解为是一个转接头&#xff0c;把用户送来过来的奇奇怪怪的query&#xff08;或者说是在搜索引擎看来是奇奇怪怪的query&#xff09;转换为搜索引擎最想看到的query的。 在LLM当前能力的帮助下&a…

STM32学习历程(day6)

EXTI外部中断使用教程 首先先看下EXTI的框图 看这个框图就能知道要先初始化GPIO外设 那么和前面一样 1、先RCC使能时钟 2、配置GPIO 选择端口为输入模式&#xff0c; 3、配置AFIO&#xff0c;选择我们用的GPIO连接到后面的EXTI 4、配置EXTI&#xff0c;选择边沿触发方式…

《系统架构设计师教程(第2版)》第11章-未来信息综合技术-06-云计算(Cloud Computing) 技术概述

文章目录 1. 相关概念2. 云计算的服务方式2.1 软件即服务 (SaaS)2.2 平台即服务 (PaaS)2.3 基础设施即服务 (IaaS)2.4 三种服务方式的分析2.4.1 在灵活性2.4.2 方便性方 3. 云计算的部署模式3.1 公有云3.2 社区云3.3 私有云3.4 混合云 4. 云计算的发展历程4.1 虚拟化技术4.2 分…

大数据如何推动工业数字化发展

在全球工业4.0浪潮中&#xff0c;大数据技术作为核心驱动力&#xff0c;正深刻改变着传统工业的面貌。通过数据的采集、分析和应用&#xff0c;工业企业能够实现生产效率的提升、成本的降低以及创新能力的增强。本文将从大数据在工业数字化中的应用场景、技术实现和实际案例等方…