Transformers快速入门代码解析(一):注意力机制——Attention:Scaled Dot-product Attention
Attention:Scaled Dot-product Attention
- 引言
- Scaled Dot-product Attention代码
引言
请注意!!!本博客使用了教程Transformers快速入门中的全部代码!!!
只在我个人理解的基础上为代码添加了注释!!!
详细教程请查看Transformers快速入门!!!
万分感谢!!!
自用!!!
Scaled Dot-product Attention代码
# torch.nn:从 PyTorch 中导入神经网络模块,用于定义嵌入层。
from torch import nn
# transformers.AutoConfig:从 Hugging Face 的 transformers 库中导入 AutoConfig,用于加载预训练模型的配置信息(如词汇大小、隐藏层大小等)。
from transformers import AutoConfig
# transformers.AutoTokenizer:用于加载与模型匹配的分词器
from transformers import AutoTokenizerimport torch
from math import sqrtimport torch.nn.functional as F# 设置模型检查点
# model_ckpt:指定 Hugging Face 模型的名称或路径,这里是 bert-base-uncased。
# bert-base-uncased 是一个预训练的 BERT 模型,大小适中,分词器会将所有文本转换为小写(uncased)。
# 你也可以选择其他模型,如 bert-large-uncased 或 distilbert-base-uncased。
model_ckpt = "bert-base-uncased"
# 加载分词器
# AutoTokenizer.from_pretrained():根据 model_ckpt 加载与预训练模型对应的分词器。
# 分词器用于将输入的自然语言文本转换为模型可以处理的 token ID。
tokenizer = AutoTokenizer.from_pretrained(model_ckpt)# 对文本进行分词和编码
# text:输入的文本数据。
text = "time flies like an arrow"
# 将输入文本转换为 token ID,返回一个 PyTorch 张量(return_tensors="pt")。
# add_special_tokens=False:不添加特殊 token(如 [CLS] 和 [SEP])。如果为 True,分词器会自动在句首和句末添加这些特殊符号。
inputs = tokenizer(text, return_tensors="pt", add_special_tokens=False)
# 每个数字表示一个 token 的 ID,具体含义可通过 tokenizer.decode 转换回原始单词。
print("==================")
print("inputs的类型,来自transformers:")
print(type(inputs))
print("==================")
print("inputs的数据,来自transformers:")
print(inputs)
print("==================")
print("inputs.input_ids的数据,pytorch类型:")
print(inputs.input_ids)
print("==================")
print("inputs.input_ids的size:")
print(inputs.input_ids.size())
print("==================")# AutoConfig.from_pretrained():
# 加载与 model_ckpt 对应的模型配置。
# config 包含模型的所有超参数(如隐藏层大小、词汇表大小、层数等)。
config = AutoConfig.from_pretrained(model_ckpt)
# 关键信息:
# config.vocab_size:模型的词汇表大小,这里为 30522(BERT 的词汇表大小)。
# config.hidden_size:每个 token 的嵌入维度,这里为 768(BERT 的默认隐藏层维度)。
# 使用 PyTorch 的 nn.Embedding 定义嵌入层。
# 输入大小:config.vocab_size,即 30522,表示词汇表中所有可能的 token。
# 输出大小:config.hidden_size,即 768,表示每个 token 的嵌入向量维度。
# 嵌入层的作用:
# 将输入的 token ID 转换为高维连续向量表示,这些向量包含了每个 token 的语义信息。
token_emb = nn.Embedding(config.vocab_size, config.hidden_size)
print("token数量以及其特征数量:")
print(token_emb)
print("==================")# inputs.input_ids:输入文本的 token ID,形状为 [1, 5](1 表示批量大小,5 表示句子中有 5 个 token)。
# inputs_embeds:将 token ID 映射到嵌入向量,嵌入的形状为 [1, 5, 768]。
# =================================================================================================
# 这相当于inputs.input_ids是序列号,要在 [30522 768]的矩阵中找到对应的序列号
# token ID,形状为 [1, 5]表示1(一句话:"time flies like an arrow"),5(这句话中有5个单词/token 的ID)
# =================================================================================================
# 1:表示批量大小。
# 5:表示句子中 token 的个数。
# 768:每个 token 的嵌入向量维度。
inputs_embeds = token_emb(inputs.input_ids)
print("给定句子的对应token及其特征:")
print(inputs_embeds)
print("==================")
print("给定句子的对应token及其特征的size:")
print(inputs_embeds.size())
print("==================")# 在自注意力机制中,每个输入向量都会被映射到三个表示:Query(查询),Key(键),Value(值)。
# Q, K, V 通常通过线性层计算,但在这段代码中,直接将 inputs_embeds 用作它们的值。-> [1, 5, 768]
Q = K = V = inputs_embeds
# 在注意力机制中,dim_k 是键向量的维度,用于归一化计算。
# 例如,如果 inputs_embeds 的形状是 [1, 5, 768](批大小为 1,序列长度为 5,嵌入维度为 768),那么 dim_k = 768。
dim_k = K.size(-1)
# torch.bmm(批量矩阵乘法):
#### torch.bmm 用于计算批次中的两个三维张量的矩阵乘法。
#### 输入的张量形状必须是 [batch_size, n, m] 和 [batch_size, m, p],输出形状为 [batch_size, n, p]。
# =================================================================================================
# K.transpose(1,2):
#### K 的形状是 [batch_size, seq_length, embedding_dim] -> [1, 5, 768]。
#### 调用 transpose(1,2) 会交换第二维和第三维,得到形状 [batch_size, embedding_dim, seq_length] -> [1, 768, 5]。
#### 这一步是为了让 K 的嵌入维度与 Q 的序列长度对齐,便于计算矩阵乘法。
# =================================================================================================
# 矩阵乘法:
#### Q 和 K.transpose(1,2) 进行矩阵乘法。
######## Q 的形状是 [batch_size, seq_length, embedding_dim] -> [1, 5, 768]。
######## K.transpose(1,2) 的形状是 [batch_size, embedding_dim, seq_length] -> [1, 768, 5]。
######## 结果 scores 的形状是 [batch_size, seq_length, seq_length] -> [1, 5, 5]。
#### 含义:
######## scores[i, j] 表示输入序列中位置 i 的查询向量 Q[i] 与位置 j 的键向量 K[j] 的点积相似度。
######## 这种相似度用于表示位置 i 关注位置 j 的程度。
# =================================================================================================
# 归一化:
#### 结果被除以 sqrt(dim_k)
#### 这是为了防止嵌入维度较大时点积值过大,导致梯度消失或梯度爆炸的问题。
scores = torch.bmm(Q, K.transpose(1,2)) / sqrt(dim_k)
print("结果(上述text这个句子中,每个单词/token之间的点积相似度):")
print(scores)
print("==================")
print("结果的size:")
print(scores.size())
print("==================")# 这段代码对前面计算得到的注意力得分矩阵 scores 进行 Softmax 操作,并验证 Softmax 操作后结果的性质(归一化)。以下是逐步的详细解析:
# 对 scores 应用 Softmax
# =================================================================================================
# F.softmax: 这是 PyTorch 中的 Softmax 函数,来自 torch.nn.functional 模块。
# =================================================================================================
# 输入参数:
#### scores 是一个三维张量,形状为 [batch_size, seq_length, seq_length] -> [1, 5, 5],表示注意力得分矩阵。
#### dim=-1 指定在最后一维(seq_length 维)上应用 Softmax,即对每个查询位置的所有键进行归一化。
# =================================================================================================
# 结果:
#### weights 是一个形状与 scores 相同的张量 [batch_size, seq_length, seq_length] -> [1, 5, 5],表示注意力权重。
#### 在 dim=-1 维上,每行的值表示一个概率分布,总和为 1。
weights = F.softmax(scores, dim=-1)
print("weights结果(上述text这个句子中,每个单词/token之间的点积相似度归一化之后的结果)")
print(weights)
print("==================")
print("weights结果加和,验证归一化:")
print(weights.sum(dim=-1))
print("==================")# 这段代码是实现 注意力机制(Attention Mechanism) 的最后一步,计算注意力输出(attn_outputs)。以下是逐行的详细解释:
# 背景:自注意力机制的核心步骤
# 在自注意力机制中,核心步骤包括:
# 1. 计算注意力得分(scores)。
# 2. 应用 Softmax 将注意力得分归一化为权重(weights)。
# 3. 将这些权重应用到值向量(V)上,得到注意力输出(attn_outputs)。
# 此代码正是在第 3 步中完成这个操作。
# weights: [batch_size, seq_length, seq_length] -> [1, 5, 5]
# V: [batch_size, seq_length, embedding_dim] -> [1, 5, 768]
# attn_outputs: [batch_size, seq_length, embedding_dim] -> [1, 5, 768]
attn_outputs = torch.bmm(weights, V)
# attn_outputs 是自注意力机制的最终结果。
# 它对输入值向量 V 进行了加权平均,权重来源于注意力权重矩阵 weights。
# 这个输出是序列中每个位置的上下文表示。
print("自注意力机制的最终结果:")
print(attn_outputs)
print("==================")
print("自注意力机制的最终结果的形状:")
print(attn_outputs.shape)
print("==================")
>>>
==================
inputs的类型,来自transformers:
<class 'transformers.tokenization_utils_base.BatchEncoding'>
==================
inputs的数据,来自transformers:
{'input_ids': tensor([[ 2051, 10029, 2066, 2019, 8612]]), 'token_type_ids': tensor([[0, 0, 0, 0, 0]]), 'attention_mask': tensor([[1, 1, 1, 1, 1]])}
==================
inputs.input_ids的数据,pytorch类型:
tensor([[ 2051, 10029, 2066, 2019, 8612]])
==================
inputs.input_ids的size:
torch.Size([1, 5])
==================
token数量以及其特征数量:
Embedding(30522, 768)
==================
给定句子的对应token及其特征:
tensor([[[ 1.2626, -2.1080, -0.6319, ..., 1.9245, -0.1595, 0.8960],[-2.1495, -1.4998, 1.2840, ..., 1.1923, -1.4115, 1.1000],[ 2.7451, -0.0587, -0.5572, ..., -0.4284, -0.2758, 0.3217],[ 0.6120, 0.7005, -0.1534, ..., 0.4005, 1.0884, 1.3846],[ 0.0194, -0.3392, 0.6146, ..., 0.4700, -2.5397, -0.1677]]],grad_fn=<EmbeddingBackward0>)
==================
给定句子的对应token及其特征的size:
torch.Size([1, 5, 768])
==================
结果(上述text这个句子中,每个单词/token之间的点积相似度):
tensor([[[28.7071, 0.4433, 0.7403, -0.4044, 0.2598],[ 0.4433, 27.8755, -0.9110, 0.0327, 1.2176],[ 0.7403, -0.9110, 27.3893, 1.3638, 0.7354],[-0.4044, 0.0327, 1.3638, 27.6121, 0.3601],[ 0.2598, 1.2176, 0.7354, 0.3601, 27.4275]]],grad_fn=<DivBackward0>)
==================
结果的size:
torch.Size([1, 5, 5])
==================
weights结果(上述text这个句子中,每个单词/token之间的点积相似度归一化之后的结果)
tensor([[[1.0000e+00, 5.3110e-13, 7.1472e-13, 2.2751e-13, 4.4206e-13],[1.2200e-12, 1.0000e+00, 3.1489e-13, 8.0912e-13, 2.6461e-12],[2.6697e-12, 5.1205e-13, 1.0000e+00, 4.9802e-12, 2.6567e-12],[6.8006e-13, 1.0529e-12, 3.9854e-12, 1.0000e+00, 1.4607e-12],[1.5895e-12, 4.1419e-12, 2.5573e-12, 1.7570e-12, 1.0000e+00]]],grad_fn=<SoftmaxBackward0>)
==================
weights结果加和,验证归一化:
tensor([[1., 1., 1., 1., 1.]], grad_fn=<SumBackward1>)
==================
自注意力机制的最终结果:
tensor([[[ 1.2626, -2.1080, -0.6319, ..., 1.9245, -0.1595, 0.8960],[-2.1495, -1.4998, 1.2840, ..., 1.1923, -1.4115, 1.1000],[ 2.7451, -0.0587, -0.5572, ..., -0.4284, -0.2758, 0.3217],[ 0.6120, 0.7005, -0.1534, ..., 0.4005, 1.0884, 1.3846],[ 0.0194, -0.3392, 0.6146, ..., 0.4700, -2.5397, -0.1677]]],grad_fn=<BmmBackward0>)
==================
自注意力机制的最终结果的形状:
torch.Size([1, 5, 768])
==================
封装好的函数:
import torch
import torch.nn.functional as F
from math import sqrt# query_mask, key_mask:
#### 用于屏蔽某些查询或键的位置。如果指定,通常是 [batch_size, seq_length] 的张量。
#### 这些掩码可以屏蔽不需要参与计算的序列位置(例如,填充位置)。
# mask:
#### 更通用的掩码,形状通常为 [batch_size, seq_length, seq_length],
#### 用于屏蔽具体的查询-键对。
def scaled_dot_product_attention(query, key, value, query_mask=None, key_mask=None, mask=None):dim_k = query.size(-1)scores = torch.bmm(query, key.transpose(1, 2)) / sqrt(dim_k)# 应用掩码(屏蔽不相关的输入)if query_mask is not None and key_mask is not None:# query_mask.unsqueeze(-1) 将查询掩码扩展为 [batch_size, seq_length, 1]。# key_mask.unsqueeze(1) 将键掩码扩展为 [batch_size, 1, seq_length]。# torch.bmm 计算两者的外积,得到形状为 [batch_size, seq_length, seq_length] 的掩码矩阵 mask。# 掩码矩阵中的值为 1 表示对应的查询-键对有效,0 表示无效。mask = torch.bmm(query_mask.unsqueeze(-1), key_mask.unsqueeze(1))if mask is not None:# 如果存在 mask,使用 masked_fill 方法将 mask == 0 的位置填充为 -inf,# 这些位置的得分被屏蔽。# Softmax 在处理 -inf 时会将其归一化为 0,从而屏蔽这些位置。scores = scores.masked_fill(mask == 0, -float("inf"))weights = F.softmax(scores, dim=-1)return torch.bmm(weights, value)
相关文章:
Transformers快速入门代码解析(一):注意力机制——Attention:Scaled Dot-product Attention
Attention:Scaled Dot-product Attention 引言Scaled Dot-product Attention代码 引言 请注意!!!本博客使用了教程Transformers快速入门中的全部代码!!! 只在我个人理解的基础上为代码添加了注释…...
Git中HEAD、工作树和索引的区别
在Git版本控制系统中,HEAD、工作树(Working Tree)和索引(Index)是三个非常重要的概念,它们分别代表了不同的状态或区域,下面我将对这三个概念进行详细的解释。 HEAD 定义:HEAD是一…...
【python量化教程】如何使用必盈API的股票接口,获取最新实时交易数据
实时交易数据简介 股票实时交易数据涵盖股票价格、成交量、涨跌幅等多类信息。其在股票交易中极为关键,高速准确的数据对各方意义重大。投资者可借此及时捕捉机会、优化策略与降低风险;实时准确的实时交易数据是股票市场有效运转的核心要素之一。 使用…...
【C++】动态内存与智能指针——shared_ptr 和 new 结合使用
12.1.3 shared_ptr 和 new 结合使用 如上文所述,如果我们不初始化一个智能指针,那么它将会被初始化为一个空指针(需要注意的是,智能指针与普通指针在此处有着非常明显的区别。如果只声明某个类型的普通指针,而不对它进…...
遥感数据集:FTW全球农田边界和对应影像数据,约160万田块边界及7万多个样本
Fields of The World (FTW) 是一个面向农业田地边界实例分割的基准数据集,旨在推动机器学习模型的发展,满足全球农业监测对高精度、可扩展的田地边界数据的需求。该数据集由kerner-lab提供,于2024年8月28日发布,主要特征包括&…...
马斯克的 AI 游戏工作室:人工智能与游戏产业的融合新纪元
近日,马斯克在 X 平台(前身为 Twitter)发文称,“太多游戏工作室被大型企业所拥有,xAI 将启动一个 AI 游戏工作室,让游戏再次变得精彩”。这一言论不仅展示了马斯克对游戏行业现状的不满,也揭示了…...
URDF(描述机器人模型)和SDF(Gazebo中用于描述仿真环境)
使用URDF(Unified Robot Description Format) URDF是ROS中用于描述机器人模型的XML格式文件。你可以使用XML文件定义机器人的几何形状、惯性参数、关节和链接等。 示例URDF文件(my_robot.urdf): <?xml version&…...
力扣380:O(1)时间插入、删除和获取随机数
实现RandomizedSet 类: RandomizedSet() 初始化 RandomizedSet 对象bool insert(int val) 当元素 val 不存在时,向集合中插入该项,并返回 true ;否则,返回 false 。bool remove(int val) 当元素 val 存在时࿰…...
【C++boost::asio网络编程】有关socket的创建和连接的笔记
socket的创建和连接 tcp客户端创建端点tcp服务端创建端点创建socket创建TCP 服务器端的 acceptor 套接字创建 acceptor 套接字并绑定客户端连接到服务器通过ip地址解析通过域名解析 服务端接收新连接 tcp客户端创建端点 int client_end_point() {std::string raw_ip_address …...
超级灵感:前端页面功能统一管理方案
前端页面功能统一管理方案 引言 我和朋友聊天想到一个灵感,关于支付状态机管理,这个类可以让我们知道具体上一个状态和下一个状态,这是由于那个事件触发改变,这个功能设计非常好! 从而讨论出为什么我们不能把某一个…...
力扣第 77 题 组合
题目描述 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按任意顺序返回答案。 示例 示例 1 输入: n 4, k 2输出: [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]示例 2 输入: n 1, k …...
(超详细图文)PLSQL Developer 配置连接远程 Oracle 服务
1、下载配置文件 (超详细图文详情)Navicat 配置连接 Oracle-CSDN博客 将下载的文件解压到单独文件夹,如:D:\App\App_Java\Oracle\instantclient-basic-windows.x64-19.25.0.0.0dbru 2、配置 打开 PLSQL Developer,登…...
元器件选型与参数13 电源的分类-线性电源参数 RT9013 AMS1117 PCB布局布线
目录 一、线性电源 1、重要参数 2、线性电源效率一定低吗 3、线性电源并联扩流 4、常见电路 RT9013-LDO AMS1117-xx-LDO 5、布局布线 6、外置输入与电池供电 7、单片机控制其他模组供电实现低功耗 二、开关电源与线性电源配合 1、高效率与低噪声 DC-DC电源大致分为…...
RHEL7+Oracle11.2 RAC集群-多路径(multipath+udev)安装步骤
RHEL7Oracle11.2RAC集群-多路径(multipathudev)安装 配置虚拟存储 使用StarWind Management Console软件,配置存储 dggrid1: 1g*3 Dggrid2: 1g*3 Dgsystem: 5g*1 系统表空间,临时表空间,UNDO,参数文件…...
每日速记10道java面试题03
其他资料 每日速记10道java面试题01-CSDN博客 每日速记10道java面试题02-CSDN博客 目录 一、你使用过java的反射机制吗?如何应用反射? 二、什么是泛型?泛型的作用是什么? 三、java的泛型擦除是什么? 四、Java 中…...
Vue 3 的双向绑定原理
Vue 3 的双向绑定原理是基于 响应式系统 和 数据劫持 技术来实现的。在 Vue 3 中,双向绑定通常是通过 v-model 指令来完成的,它本质上是数据的双向同步:当数据改变时,视图自动更新,反之,视图的修改也会更新…...
如何使用 Chrome 无痕浏览模式访问网站?
无痕浏览(Incognito Mode)是 Google Chrome 浏览器提供的一种隐私保护功能,它允许用户在一个独立的会话中浏览网页,而不会记录用户的浏览历史、下载历史、表单数据等。这对于希望保护个人隐私或进行临时性匿名浏览的用户来说非常有…...
Idea 2024.3 突然出现点击run 运行没有反应,且没有任何提示。
写这篇文章的目的是为了提供一个新的解决思路,因为存在同病不同原因。 如果你进行了1. 检查运行配置 (Run Configuration) 2. 清理和重建项目 3. 清除缓存并重启 IDEA 4.排除kotlin 5.重装idea等等操作之后仍然没有解决,可以试着按一下步骤进行解决。 检…...
【小白学机器学习36】关于独立概率,联合概率,交叉概率,交叉概率和,总概率等 概念辨析的例子
目录 1 先说结论 2 联合概率 3 边缘概率 4 (行/列)边缘概率的和 总概率1 5 条件概率 5.1 条件概率的除法公式 5.2 条件概率和联合概率区别 1 先说结论 关于独立概率,联合概率,交叉概率,交叉概率和,总概率 类型含义 …...
Spring Boot 项目——分层架构
在创建一个 Spring Boot 项目时,为了提高代码的可维护性、可扩展性和清晰度,通常会按照一定的分层架构进行设计。常见的分层架构包括以下几层: 1. Controller 层(Web 层) 作用:接收用户请求,并…...
wordpress网站首页底部栏显示网站备案信息
一、页脚文件footer.php 例如,wordpress主题使用的是simple-life主题,服务器IP为192.168.68.89,在wordpress主题文件中有个页脚文件footer.php,这是一个包含网站页脚代码的文件。 footer.php 路径如下: /www/wwwroot/192.168.68…...
python面向对象编程练习
学生成绩管理系统 定义一个Student类,包括属性(姓名、成绩)和方法(设置成绩、获取成绩、计算平均成绩)。 实例化多个学生对象并调用方法。 功能说明: Student 类: init(self, name):…...
OpenCV_Code_LOG
孔洞填充 void fillHole(const Mat srcBw, Mat &dstBw) {Size m_Size srcBw.size();Mat TempMat::zeros(m_Size.height2,m_Size.width2,srcBw.type());//延展图像srcBw.copyTo(Temp(Range(1, m_Size.height 1), Range(1, m_Size.width 1)));cv::floodFill(Temp, Point(…...
力扣第 74 题是 搜索二维矩阵
题目描述 给定一个 m x n 的矩阵 matrix 和一个目标值 target,请你编写一个函数来判断目标值 target 是否在矩阵中。 每行的元素按升序排列。每列的元素按升序排列。 示例 1 输入: matrix [[1, 4, 7, 11],[2, 5, 8, 12],[3, 6, 9, 16],[10, 13, 14…...
[极客大挑战 2019]BabySQL--详细解析
信息搜集 进入界面: 输入用户名为admin,密码随便输一个: 发现是GET传参,有username和password两个传参点。 我们测试一下password点位能不能注入: 单引号闭合报错,根据报错信息,我们可以判断…...
实现Linux平台自定义协议族
一 简介 我们常常在Linux系统中编写socket接收TCP/UDP协议数据,大家有没有想过它怎么实现的,如果我们要实现socket接收自定义的协议数据又该怎么做呢?带着这个疑问,我们一起往下看吧~~ 二 Linux内核函数简介 在Linux系统中要想…...
RL78/G15 Fast Prototyping Board Arduino IDE 平台开发过程
这是一篇基于RL78/G15 Fast Prototyping Board的Arduino IDE开发记录 RL78/G15 Fast Prototyping Board硬件简介(背景)基础测试(方法说明/操作说明)开发环境搭建(方法说明/操作说明代码结果)Arduino IDE RL…...
YOLOv11 NCNN安卓部署
YOLOv11 NCNN安卓部署 前言 yolov11 NCNN安卓部署 目前的帧率可以稳定在20帧左右,下面是这个项目的github地址:https://github.com/gaoxumustwin/ncnn-android-yolov11 上面的检测精度很低时因为这个模型只训练了5个epoch,使用3090训练一个…...
对载入的3dtiles进行旋转、平移和缩放变换。
使用 params: {tx: 129.75845, //模型中心X轴坐标(经度,单位:十进制度)//小左ty: 46.6839, //模型中心Y轴坐标(纬度,单位:十进制度)//小下tz: 28, //模型中心Z轴坐标(高…...
Rust个人认为将抢占C和C++市场,逐渐成为主流的开发语言
本人使用C开发8年、C#开发15年、中间使用JAVA开发过项目、后期在学习过程中发现了Rust语言说它是最安全的语言,能够解决C、C的痛点、于是抽出一部分时间网上买书,看网上资料进行学习,这一学习起来发现和其它语言比较起来,在编码的…...
湖南品牌网站建站可定制/本网站三天换一次域名
2019独角兽企业重金招聘Python工程师标准>>> hdfs优点: -高容错性:多副本;副本丢失后可以自动恢复-适合批处理:移动计算而非数据;数据位置暴露给计算框架-适合大数据库处理:TB,PB量级数据处理&a…...
晋中网站建设公司/站长工具ip查询
IComparable接口:在要比较的对象的类中实现,可以比较该对象和另一个对象。 实现 public int CompareTo(object obj) {} IComparer接口:在一个单独的类中实现,可以比较任意两个对象。 实现 public int Compare(object x,object y) …...
wap网站做微信小程序/今日头条10大新闻
Redux是JavaScript状态容器,提供可预测化的状态管理。在实际开发中,常搭配React React-redux使用。这代表了目前前端开发的一个基本理念,数据和视图的分离。redux应运而生,当然还有其他的一些状态管理库,如Flux、Elm等…...
wordpress绑定网站/济南百度公司
哈夫曼树的带权路径长度是什么?1.树的路径长度树的路径长度是从树根到树中每一结点的路径长度之和。在结点数目相同的二叉树中,完全二叉树的路径长度最短。2.树的带权路径长度(Weighted Path Length of Tree,简记为WPL…...
北京网站建设 标准型 新翼/建设网页
分布式编程模型的背景 编程模型是指编程的方法而不是特指某一种编程语言,如面向对象的编程就是一种编程模型。编程模型大致分为两类:命令式编程和声明式编程。前者最典型的是面向过程的编程语言,如C语言;后者与前者差异较大&#…...
做一个网站做少多少钱/帮我搜一下长沙做网络销售
本文转自:http://blogs.msdn.com/b/azchina/archive/2010/03/11/windows-azure-table-storage.aspx 本文是Windows Azure入门教学的第六篇文章。 本文将会介绍如何使用Table Storage。Table Storage提供给我们一个云端的表格结构。我们可以把他想象为XML文件或者是一…...