机器学习系列----深入理解Transformer模型

在过去的几年里,Transformer模型彻底改变了自然语言处理(NLP)领域,并扩展到计算机视觉、语音处理等多个领域。Transformer架构自2017年由Vaswani等人提出以来,凭借其强大的性能和高效的并行计算能力,成为了现代深度学习中最重要的模型之一。在这篇文章中,我们将深入分析Transformer的核心原理,并通过代码示例帮助大家理解其实际实现。

一.Transformer模型概述

    Transformer模型的最大特点是基于“自注意力机制”(Self-Attention),它不依赖于传统的循环神经网络(RNN)或卷积神经网络(CNN),而是通过并行计算高效地处理序列数据。Transformer模型包含两个主要部分:编码器(Encoder)和解码器(Decoder)。每个部分由多个相同的层组成,每层包含不同的子组件。接下来,我们将逐一分析Transformer模型的关键组成部分。

1. 自注意力机制(Self-Attention)

自注意力机制允许模型在处理输入序列时,考虑序列中所有单词之间的关系。具体来说,给定一个输入词,它会根据该词与序列中其他所有词之间的相似度来更新自己的表示。

自注意力计算步骤
假设输入是一个词序列,其中每个词会被转换成一个向量。自注意力机制通过以下步骤计算每个词的最终表示:

步骤1:计算每个输入向量的 Query(Q)、Key(K) 和 Value(V) 向量。
步骤2:计算 Query 和 Key 之间的相似度,通常使用点积(Dot Product),然后进行 softmax 操作,得到每个词的注意力权重。
步骤3:使用这些权重对 Value 向量进行加权求和,得到新的表示。
代码示例:自注意力机制实现

import torch
import torch.nn.functional as Fdef self_attention(Q, K, V):# 计算Q和K的点积scores = torch.matmul(Q, K.transpose(-2, -1)) / Q.size(-1) ** 0.5# 使用softmax归一化得分attention_weights = F.softmax(scores, dim=-1)# 通过注意力权重加权求和Voutput = torch.matmul(attention_weights, V)return output, attention_weights# 假设Q, K, V的形状为 (batch_size, num_heads, seq_len, d_k)
Q = torch.randn(1, 8, 10, 64)  # Batch size: 1, Heads: 8, Seq_len: 10, d_k: 64
K = torch.randn(1, 8, 10, 64)
V = torch.randn(1, 8, 10, 64)output, attention_weights = self_attention(Q, K, V)
print(output.shape)  # (1, 8, 10, 64)

2. 多头注意力机制(Multi-Head Attention)
为了让模型能够捕捉到输入数据中不同子空间的依赖关系,Transformer使用了 多头注意力机制。多头注意力机制并行计算多个自注意力头,每个头学习不同的注意力模式,最后将多个头的输出拼接起来,再进行一次线性变换。

代码示例:多头注意力实现

class MultiHeadAttention(torch.nn.Module):def __init__(self, d_model, num_heads):super(MultiHeadAttention, self).__init__()self.num_heads = num_headsself.d_model = d_modelassert d_model % num_heads == 0, "d_model must be divisible by num_heads"self.d_k = d_model // num_headsself.Q_linear = torch.nn.Linear(d_model, d_model)self.K_linear = torch.nn.Linear(d_model, d_model)self.V_linear = torch.nn.Linear(d_model, d_model)self.out_linear = torch.nn.Linear(d_model, d_model)def forward(self, Q, K, V):batch_size = Q.size(0)# 线性变换并分成多头Q = self.Q_linear(Q).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)K = self.K_linear(K).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)V = self.V_linear(V).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)# 自注意力计算output, attention_weights = self._scaled_dot_product_attention(Q, K, V)# 拼接各个头的输出output = output.transpose(1, 2).contiguous().view(batch_size, -1, self.d_model)output = self.out_linear(output)return output, attention_weightsdef _scaled_dot_product_attention(self, Q, K, V):scores = torch.matmul(Q, K.transpose(-2, -1)) / self.d_k ** 0.5attention_weights = F.softmax(scores, dim=-1)output = torch.matmul(attention_weights, V)return output, attention_weights# 测试多头注意力机制
multi_head_attention = MultiHeadAttention(d_model=256, num_heads=8)
Q = torch.randn(32, 10, 256)  # Batch size: 32, Sequence length: 10, d_model: 256
K = torch.randn(32, 10, 256)
V = torch.randn(32, 10, 256)output, attention_weights = multi_head_attention(Q, K, V)
print(output.shape)  # (32, 10, 256)

3. 位置编码(Positional Encoding)
由于Transformer没有像RNN那样内建的顺序信息,因此需要通过 位置编码 来向模型提供输入词的位置信息。位置编码通常使用正弦和余弦函数生成,具有周期性,以便模型能够学习到不同词位置之间的相对关系。

代码示例:位置编码实现

import numpy as np
import torchclass PositionalEncoding(torch.nn.Module):def __init__(self, d_model, max_len=5000):super(PositionalEncoding, self).__init__()pe = torch.zeros(max_len, d_model)position = torch.arange(0, max_len).float().unsqueeze(1)div_term = torch.exp(torch.arange(0, d_model, 2).float() * -(np.log(10000.0) / d_model))pe[:, 0::2] = torch.sin(position * div_term)pe[:, 1::2] = torch.cos(position * div_term)pe = pe.unsqueeze(0)self.register_buffer('pe', pe)def forward(self, x):return x + self.pe[:, :x.size(1)]# 测试位置编码
pos_encoder = PositionalEncoding(d_model=256)
x = torch.randn(32, 10, 256)  # Batch size: 32, Seq length: 10, d_model: 256
encoded_x = pos_encoder(x)
print(encoded_x.shape)  # (32, 10, 256)

 4. 编码器和解码器
Transformer模型由多个相同的编码器和解码器组成。每个编码器层包括一个 多头自注意力机制 和一个 前馈神经网络,解码器则在此基础上增加了一个 多头注意力机制 用于与编码器的输出交互。我们通过堆叠多个这些层,构建一个强大的模型。

5. 编码器和解码器的堆叠

class TransformerEncoderLayer(torch.nn.Module):def __init__(self, d_model, num_heads, ff_hidden_dim):super(TransformerEncoderLayer, self).__init__()self.attn = MultiHeadAttention(d_model, num_heads)self.ffn = torch.nn.Sequential(torch.nn.Linear(d_model, ff_hidden_dim),torch.nn.ReLU(),torch.nn.Linear(ff_hidden_dim, d_model))self.norm1 = torch.nn.LayerNorm(d_model)self.norm2 = torch.nn.LayerNorm(d_model)def forward(self, x):attn_output, _ = self.attn(x, x, x)x = self.norm1(x + attn_output)ffn_output = self.ffn(x)x = self.norm2(x + ffn_output)return xclass Transformer(torch.nn.Module):def __init__(self, d_model, num_heads, num_layers, ff_hidden_dim, vocab_size, max_len=5000):super(Transformer, self).__init__()self.embedding = torch.nn.Embedding(vocab_size, d_model)self.pos_encoder = PositionalEncoding(d_model)self.encoder_layers = torch.nn.ModuleList([TransformerEncoderLayer(d_model, num_heads, ff_hidden_dim) for _ in range(num_layers)])self.decoder = torch.nn.Linear(d_model, vocab_size)def forward(self, x):# 通过嵌入层x = self.embedding(x)# 加入位置编码x = self.pos_encoder(x)# 通过多个编码器层for layer in self.encoder_layers:x = layer(x)# 最后通过解码器层输出词汇表大小的预测logits = self.decoder(x)return logits# 测试Transformer模型
vocab_size = 10000  # 假设词汇表大小为10,000
seq_len = 20  # 输入序列长度为20
batch_size = 32
d_model = 256  # 嵌入维度
num_heads = 8  # 注意力头数
num_layers = 6  # 编码器层数
ff_hidden_dim = 1024  # 前馈神经网络的隐藏层维度model = Transformer(d_model, num_heads, num_layers, ff_hidden_dim, vocab_size)# 假设输入是一个批次的词序列(词汇表中的索引)
input_sequence = torch.randint(0, vocab_size, (batch_size, seq_len))# 模型前向传播
output = model(input_sequence)
print(output.shape)  # 输出的形状应该是 (batch_size, seq_len, vocab_size)

二.实际运用----基于PyTorch实现的情感分析模型

下面是一个基于PyTorch实现的Transformer模型的应用实例。该示例展示了如何使用Transformer模型进行文本分类任务,具体的任务是对IMDB电影评论数据集进行情感分析。

我们会构建一个文本分类模型,它的输入是一个电影评论文本,输出是该评论的情感分类(正面或负面)。在这个示例中,我们会利用PyTorch的nn.Transformer类和一些常见的深度学习技术来实现。

1. 环境配置与数据加载

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import numpy as np
from tqdm import tqdm
import spacy# 使用spaCy加载英文模型,用于分词
nlp = spacy.load("en_core_web_sm")# 加载IMDB数据集,通常可以通过torchtext或自己下载
def load_imdb_data():# 这里假设你已经将IMDB数据集下载到本地# 你可以在网上找到数据集,并将其转换为文本和标签# 这里只是一个模拟,实际使用时你需要具体实现数据加载texts = ["This movie was great!", "I hated this movie.", "Amazing acting and story!", "Worst movie ever.", ...]labels = [1, 0, 1, 0, ...]  # 1表示正面,0表示负面return texts, labels# 数据预处理函数:tokenize和创建词汇表
def preprocess(texts, vocab_size=10000):# 使用spaCy进行文本预处理tokenized_texts = []for text in texts:doc = nlp(text)tokenized_texts.append([token.text for token in doc if not token.is_stop and not token.is_punct])# 创建词汇表word_freq = {}for tokens in tokenized_texts:for token in tokens:word_freq[token] = word_freq.get(token, 0) + 1# 排序并选择最常见的词汇vocab = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)[:vocab_size]vocab = {word: idx + 2 for idx, (word, _) in enumerate(vocab)}  # 给每个词分配一个索引,0和1预留给padding和未知词# 添加特殊的padding和未知符号vocab['<PAD>'] = 0vocab['<UNK>'] = 1# 将文本转换为索引texts_idx = []for tokens in tokenized_texts:texts_idx.append([vocab.get(token, vocab['<UNK>']) for token in tokens])return texts_idx, vocab# 数据集类
class IMDBDataset(Dataset):def __init__(self, texts, labels):self.texts = textsself.labels = labelsdef __len__(self):return len(self.texts)def __getitem__(self, idx):return torch.tensor(self.texts[idx]), torch.tensor(self.labels[idx])# 加载数据
texts, labels = load_imdb_data()
texts_idx, vocab = preprocess(texts)
train_texts, val_texts, train_labels, val_labels = train_test_split(texts_idx, labels, test_size=0.2)train_dataset = IMDBDataset(train_texts, train_labels)
val_dataset = IMDBDataset(val_texts, val_labels)train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)

2. 定义Transformer模型

class TransformerTextClassifier(nn.Module):def __init__(self, vocab_size, embed_size, num_heads, num_layers, ff_hidden_dim, num_classes, max_len=500):super(TransformerTextClassifier, self).__init__()self.embedding = nn.Embedding(vocab_size, embed_size, padding_idx=0)self.pos_encoder = nn.TransformerEncoderLayer(embed_size, num_heads, ff_hidden_dim)self.encoder = nn.TransformerEncoder(self.pos_encoder, num_layers)self.fc = nn.Linear(embed_size, num_classes)self.max_len = max_lendef forward(self, x):# x: (batch_size, seq_len)batch_size, seq_len = x.size()# 获取位置编码positions = torch.arange(0, seq_len, device=x.device).unsqueeze(0).repeat(batch_size, 1)# 词嵌入 + 位置编码x = self.embedding(x) + positions.float()# 转换为 (seq_len, batch_size, embed_size)x = x.permute(1, 0, 2)# 通过Transformer编码器x = self.encoder(x)# 取最后一个时间步的输出x = x[-1, :, :]# 分类层x = self.fc(x)return x

3. 训练与验证模型

# 超参数设置
vocab_size = len(vocab)
embed_size = 256
num_heads = 8
num_layers = 6
ff_hidden_dim = 512
num_classes = 2  # 正面和负面
learning_rate = 0.001
num_epochs = 10# 实例化模型
model = TransformerTextClassifier(vocab_size, embed_size, num_heads, num_layers, ff_hidden_dim, num_classes)# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)# 训练函数
def train(model, train_loader, optimizer, criterion):model.train()total_loss = 0correct_preds = 0total_preds = 0for texts, labels in tqdm(train_loader, desc="Training"):optimizer.zero_grad()# 转换为长整型texts, labels = texts.long(), labels.long()# 前向传播outputs = model(texts)# 计算损失loss = criterion(outputs, labels)loss.backward()optimizer.step()total_loss += loss.item()# 计算准确度_, predicted = torch.max(outputs, 1)correct_preds += (predicted == labels).sum().item()total_preds += labels.size(0)avg_loss = total_loss / len(train_loader)accuracy = correct_preds / total_preds * 100return avg_loss, accuracy# 验证函数
def evaluate(model, val_loader, criterion):model.eval()total_loss = 0correct_preds = 0total_preds = 0with torch.no_grad():for texts, labels in tqdm(val_loader, desc="Evaluating"):texts, labels = texts.long(), labels.long()outputs = model(texts)loss = criterion(outputs, labels)total_loss += loss.item()_, predicted = torch.max(outputs, 1)correct_preds += (predicted == labels).sum().item()total_preds += labels.size(0)avg_loss = total_loss / len(val_loader)accuracy = correct_preds / total_preds * 100return avg_loss, accuracy# 训练与验证
for epoch in range(num_epochs):train_loss, train_accuracy = train(model, train_loader, optimizer, criterion)val_loss, val_accuracy = evaluate(model, val_loader, criterion)print(f"Epoch {epoch + 1}/{num_epochs}")print(f"Train Loss: {train_loss:.4f}, Train Accuracy: {train_accuracy:.2f}%")print(f"Val Loss: {val_loss:.4f}, Val Accuracy: {val_accuracy:.2f}%")

4. 测试与推理

# 使用训练好的模型进行预测
def predict(model, text, vocab, max_len=500):model.eval()# 预处理输入文本tokens = [token.text for token in nlp(text) if not token.is_stop and not token.is_punct]text_idx = [vocab.get(token, vocab['<UNK>']) for token in tokens]text_idx = text_idx[:max_len]  # 限制最大长度text_idx += [vocab['<PAD>']] * (max_len - len(text_idx))  # 填充到最大长度input_tensor = torch.tensor(text_idx).unsqueeze(0)  # 增加批次维度# 进行预测with torch.no_grad():output = model(input_tensor)prediction = torch.argmax(output, dim=1).item()return "Positive" if prediction == 1 else "Negative"# 示例预测
sample_text = "The movie was absolutely fantastic! I loved it."
print(predict(model, sample_text, vocab))

三.总结

Transformer模型是一种基于自注意力(Self-Attention)机制的深度学习架构,最早由Vaswani等人在2017年提出,主要用于自然语言处理(NLP)任务。与传统的循环神经网络(RNN)和长短期记忆网络(LSTM)不同,Transformer不依赖于序列的顺序处理,而是通过自注意力机制来捕捉输入序列中任意位置之间的依赖关系。该模型的核心思想是,通过计算输入序列中每个位置与其他所有位置的相似度,来动态地加权每个位置的信息,从而有效地捕捉长距离依赖。

Transformer的结构分为两部分:编码器(Encoder)和解码器(Decoder)。编码器负责对输入序列进行处理,提取出输入的高阶特征;解码器则将这些特征转化为输出序列。在许多任务中(如文本分类和机器翻译的编码部分),我们通常只使用Transformer的编码器部分。Transformer的最大特点是其完全并行化的计算方式,这使得它比传统的RNN/LSTM模型在训练时更高效,尤其在大规模数据集上表现更为突出。

Transformer的关键组件包括自注意力层(Self-Attention Layer)和位置编码(Positional Encoding)。自注意力层通过计算每个输入单元与其他单元的相似度,生成加权的表示。而位置编码则解决了序列顺序问题,因为Transformer本身并没有递归结构,无法显式地捕捉位置信息。通过位置编码,可以为每个输入单元添加位置信息,使得模型能够理解序列中的相对位置关系。

Transformer的优势不仅体现在高效的计算和长距离依赖建模上,还使得它成为多种NLP任务(如机器翻译、文本生成、情感分析等)和跨领域应用(如计算机视觉和生物信息学)的基石。许多后续的模型,如BERT、GPT等,都是在Transformer基础上发展而来,推动了自然语言处理技术的飞跃。

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

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

相关文章

自然语言处理在客户服务中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 自然语言处理在客户服务中的应用 自然语言处理在客户服务中的应用 自然语言处理在客户服务中的应用 引言 自然语言处理概述 定义…

【Ubuntu24.04】从双系统到虚拟机再到单系统的故事

故事 在大学前期&#xff0c;我使用Ubuntu系统都是为了学习一些命令或者其它Linux的东西&#xff0c;对性能的要求不高&#xff0c;所以选择了虚拟机&#xff0c;后来为了做毕设&#xff0c;选择安装了Ubuntu20.04双系统&#xff0c;因为虚拟机实在带不动&#xff0c;那时我的主…

初次体验Tauri和Sycamore(1)

原创作者&#xff1a;庄晓立&#xff08;LIIGO&#xff09; 原创时间&#xff1a;2024年11月10日 原创链接&#xff1a;https://blog.csdn.net/liigo/article/details/143666827 版权所有&#xff0c;转载请注明出处。 前言 Tauri 2.0发布于2024年10月2日&#xff0c;Sycamore…

【统计子矩阵——部分前缀和+双指针】

题目 代码 #include <bits/stdc.h> using namespace std; typedef long long ll; const int N 510; int s[N][N]; int main() {ios::sync_with_stdio(0);cin.tie(0);int n, m, k;cin >> n >> m >> k;for(int i 1; i < n; i)for(int j 1; j <…

「QT」QT5程序设计专栏目录

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「QT」QT5程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasolid…

Qt学习笔记第41到50讲

第41讲 UI美化遗留问题解决 如上图所示目前记事本的雏形已现&#xff0c;但是还是有待优化&#xff0c;比如右下角的拖动问题。 解决方法&#xff1a; ①首先修改了Widget类的构造函数。 Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) {ui->s…

深度学习经典模型之ZFNet

1 ZFNet 1.1 模型介绍 ​ ZFNet是由 M a t t h e w Matthew Matthew D . Z e i l e r D. Zeiler D.Zeiler和 R o b Rob Rob F e r g u s Fergus Fergus在AlexNet基础上提出的大型卷积网络&#xff0c;在2013年ILSVRC图像分类竞赛中以11.19%的错误率获得冠军&#xff08;实际…

移动应用开发:简易登录页

文章目录 简介一&#xff0c;创建新活动二&#xff0c;设计UI布局三&#xff0c;编写活动代码四&#xff0c;运行应用程序注意 简介 使用Android Studio编写的简单Android 登录应用程序&#xff0c;该应用程序包含一个登录界面&#xff0c;具有账号和密码两个文本框&#xff0…

网络基础:http协议和内外网划分

声明 学习视频来自B站UP主泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 泷羽sec的个人空间-泷羽sec个人主页-哔哩哔哩视频https://space.bilibili.com/350329294 一&#xff0c;H…

英飞凌Aurix2G TC3XX GPT12模块详解

英飞凌Aurix2G TC3XX GPT12模块详解 本文主要介绍英飞凌 Aurix2G TC3XX系列芯片GPT12模块硬件原理、MCAL相关配置和部分代码实现。 文章目录 英飞凌Aurix2G TC3XX GPT12模块详解1 模块介绍2 功能介绍2.1 结构2.2 独立运行模式2.2.1 定时器模式2.2.2 门控定时器模式2.2.3 计数…

大数据程序猿不可不看的资料大全

​ 随着大数据技术的发展&#xff0c;大数据程序猿在数据采集、处理、分析、存储等方面的技能需求不断增加。要在这个领域保持竞争力&#xff0c;系统性地学习和掌握大数据工具、技术架构和行业趋势是非常重要的。以下为您提供一份围绕大数据程序猿不可不看的资料大全&#xf…

抓包工具WireShark使用记录

目录 网卡选择&#xff1a; 抓包流程&#xff1a; 捕获过滤器 常用捕获过滤器&#xff1a; 抓包数据的显示 显示过滤器&#xff1a; 常用的显示过滤器&#xff1a; 实际工作中&#xff0c;在平台对接&#xff0c;设备对接等常常需要调试接口&#xff0c;PostMan虽然可以进…

MySQL数据迁移到SQLServer数据库

随着云计算技术的发展以及大数据时代的到来&#xff0c;越来越多的企业开始寻求更加高效、安全的数据管理解决方案。MySQL作为一种开源的关系型数据库管理系统&#xff0c;在互联网应用开发中占据了极其重要的位置&#xff1b;而另一方面&#xff0c;Microsoft SQL Server凭借其…

【STM32开发】-FreeRTOS开发入手学习

一、什么是FreeRTOS&#xff1f; FreeRTOS 是 RTOS 系统的一种&#xff0c;FreeRTOS 十分的小巧&#xff0c;可以在资源有限的微控制器中运行&#xff1b; 1、 FreeRTOS是免费的。 2、许多其他半导体厂商产品的 SDK 包就使用 FreeRTOS 作为其操作系统&#xff0c;尤其是 WIFI、…

【软考】系统分析师第二版 新增章节 第20章微服务系统分析与设计

微服务系统是一类基于微服务架构风格的分布式系统&#xff0c;它将应用程序拆分成多个独立的小型服务&#xff0c;每个服务都运行在独立的进程中&#xff0c;并采用轻量级通信协议进行通信。这些服务可以由不同的团队开发、不同的编程语言编写&#xff0c;并且可以按需部署。微…

【笔记】自动驾驶预测与决策规划_Part6_不确定性感知的决策过程

文章目录 0. 前言1. 部分观测的马尔可夫决策过程1.1 POMDP的思想以及与MDP的联系1.1.1 MDP的过程回顾1.1.2 POMDP定义1.1.3 与MDP的联系及区别POMDP 视角MDP 视角决策次数对最优解的影响 1.2 POMDP的3种常规解法1.2.1 连续状态的“Belief MDP”方法1. 信念状态的定义2. Belief …

【SpringBoot】 黑马大事件笔记-day2

目录 用户部分 实体类属性的参数校验 更新用户密码 文章部分 规定josn日期输出格式 分组校验 上期回顾&#xff1a;【SpringBoot】 黑马大事件笔记-day1 用户部分 实体类属性的参数校验 对应的接口文档&#xff1a; 基本信息 请求路径&#xff1a;/user/update 请求方式&#…

HarmonyOS入门 : 获取网络数据,并渲染到界面上

1. 环境搭建 开发HarmonyOS需要安装DevEco Studio&#xff0c;下载地址 : https://developer.huawei.com/consumer/cn/deveco-studio/ 2. 如何入门 入门HarmonyOS我们可以从一个实际的小例子入手&#xff0c;比如获取网络数据&#xff0c;并将其渲染到界面上。 本文就是基于…

AndroidStudio-视图基础

一、设置视图的宽高 1.在XML文件中设置视图宽高 视图宽度通过属性android:layout_width表达&#xff0c;视图高度通过属性android:layout_height表达&#xff0c;宽高的取值主要有下列三种: &#xff08;1&#xff09;wrap_content:表示与内容自适应。对于文本视图来说&…

三菱QD77MS定位模块紧急停止功能

“紧急停止功能” 是通过简单运动模块的外部输入连接用连接器上连接的紧急停止输入&#xff0c;对同服放大器的全部轴进行批量停止的功能。(初始值为“0:有效”。)通过“[r.82]紧急停止有效/无效设置”可以选择紧急停止输入的有效/无效。 [1]控制内容 将“[r82]紧急停止有效/无…