游戏AI的创造思路-技术基础-深度学习(7)TF

重头戏TF,汽车人,变形~~~~

现在广泛应用的GPT中,数据处理的关键点就是Transformer算法,多次多层的映射“变形”造就了其对自然语言处理能力的提升,但本篇介绍的内容中,Transformer算法是用来构建游戏AI的“思考”-“预言”或者“猜想”-“证言”-输出为主

3.7.Transformer算法

3.7.1. 定义

Transformer算法是一种基于自注意力机制的神经网络结构,由Vaswani等人在2017年提出,最初应用于机器翻译任务。

它通过多层自注意力机制和前馈神经网络对输入序列和输出序列进行处理,实现序列到序列的映射转换。

3.7.2. 历史

在Transformer模型提出之前,自然语言处理(NLP)任务主要依赖于循环神经网络(RNN)和长短期记忆网络(LSTM)。

然而,这些模型在处理长序列和长距离依赖关系时存在局限性,并且难以并行化。为了解决这些问题,Vaswani等人提出了Transformer模型,它完全基于自注意力机制,极大地提高了处理长序列和并行计算的能力。

3.7.3. 运行原理

Transformer的运行原理主要基于自注意力机制(Self-Attention)(特别是多头注意力(Multi-Head Attention))编码器-解码器(Encoder-Decoder)架构,以下是对其运行原理的详细描述:

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

自注意力机制是Transformer模型的核心组件,它允许模型在处理序列中的每个元素时,都能够关注到序列中的其他所有元素,从而捕捉序列内部的依赖关系。具体步骤如下:

输入表示

  • 首先,将输入序列中的每个元素(如单词、图像块等)转换为固定维度的向量表示。这些向量表示可以通过嵌入层(Embedding Layer)得到,嵌入层通常是一个可学习的参数矩阵。输入首先通过一个嵌入层(Embedding Layer),将每个词转换为一个固定大小的向量。然后,通常还会加上位置编码(Positional Encoding),以保留词序信息。
import torch  
import torch.nn as nn  
import math  
  
class PositionalEncoding(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, dtype=torch.float).unsqueeze(1)  
        div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.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).transpose(0, 1)  
        self.register_buffer('pe', pe)  
  
    def forward(self, x):  
        return x + self.pe[:x.size(0), :]  
  
# 假设 embed_size 是嵌入向量的维度  
embed_size = 512  
max_len = 600  
positional_encoding = PositionalEncoding(embed_size, max_len)

生成Query、Key、Value矩阵

对于序列中的每个向量表示,通过线性变换分别生成三个新的向量:查询向量(Query, Q)、键向量(Key, K)和值向量(Value, V)。这些线性变换的参数是模型需要学习的。

输入向量通过三个不同的线性层来生成 Query(Q),Key(K),Value(V)矩阵。

class SelfAttention(nn.Module):  
    def __init__(self, embed_size, heads):  
        super(SelfAttention, self).__init__()  
        self.embed_size = embed_size  
        self.heads = heads  
        self.head_dim = embed_size // heads  
  
        assert self.head_dim * heads == embed_size, "Embedding size needs to be divisible by heads"  
  
        self.values = nn.Linear(self.head_dim, self.head_dim, bias=False)  
        self.keys = nn.Linear(self.head_dim, self.head_dim, bias=False)  
        self.queries = nn.Linear(self.head_dim, self.head_dim, bias=False)  
        self.fc_out = nn.Linear(heads * self.head_dim, embed_size)  
  
    def forward(self, values, keys, query, mask):  
        N = query.shape[0]  
        value_len, key_len, query_len = values.shape[1], keys.shape[1], query.shape[1]  
  
        # 切分嵌入层到self.heads不同切块  
        values = values.reshape(N, value_len, self.heads, self.head_dim)  
        keys = keys.reshape(N, key_len, self.heads, self.head_dim)  
        queries = query.reshape(N, query_len, self.heads, self.head_dim)  
          
        values = self.values(values)  
        keys = self.keys(keys)  
        queries = self.queries(queries)

计算注意力分数

对于序列中的每个查询向量,计算它与所有键向量的点积,得到注意力分数。这些分数衡量了查询向量与序列中每个元素之间的相关性。

计算 Query 和 Key 的点积,得到注意力分数,然后应用 softmax 函数进行归一化。

energy = torch.einsum("nqhd,nkhd->nhqk", [queries, keys])  
          
        if mask is not None:  
            energy = energy.masked_fill(mask == 0, float("-1e20"))  
  
        attention = torch.softmax(energy / (self.embed_size ** (1 / 2)), dim=3)

缩放点积注意力(Scaled Dot-Product Attention)

为了防止点积结果过大导致softmax函数进入饱和区,将点积结果除以一个缩放因子(通常是输入向量维度的平方根)。然后,通过softmax函数对缩放后的点积结果进行归一化,得到注意力权重。点积的结果除以维度的平方根来进行缩放,有助于梯度稳定。

加权求和

使用注意力权重对值向量进行加权求和,得到每个查询向量的上下文表示。这个上下文表示包含了序列中所有元素对当前查询向量的贡献。

用注意力分数对 Value 进行加权求和,得到最终的输出。

out = torch.einsum("nhql,nlhd->nqhd", [attention, values]).reshape(N, query_len, self.heads * self.head_dim)  
          
        out = self.fc_out(out)  
        return out

 这样,我们就完成了一个自注意力层的实现。在实际使用时,可以将这个层嵌入到更大的 Transformer 网络中。

3.7.3.2. 多头注意力(Multi-Head Attention)

为了提高模型的表示能力,Transformer使用多头注意力机制。具体步骤如下:

  1. 分割输入
    • 将输入向量分割成多个头(Head),每个头独立地进行自注意力计算。
  2. 并行计算
    • 每个头都有自己的查询、键、值矩阵和自注意力计算过程。这些计算过程是并行的,可以显著提高模型的计算效率。
  3. 拼接与线性变换
    • 将所有头的输出拼接在一起,然后通过一个线性变换得到最终的多头注意力输出。这个线性变换的参数也是模型需要学习的。
3.7.3.3. 编码器-解码器(Encoder-Decoder)架构

Transformer模型由编码器和解码器两部分组成,它们分别负责输入序列的编码和输出序列的生成。

3.7.3.3.1. 编码器(Encoder)
  1. 多层堆叠
    • 编码器由多个相同的编码器层堆叠而成。每个编码器层都包含自注意力子层、前馈神经网络子层以及残差连接和层归一化。
  2. 自注意力子层
    • 自注意力子层负责捕捉输入序列内部的依赖关系,生成每个元素的上下文表示。
  3. 前馈神经网络子层
    • 前馈神经网络子层是一个逐位置的前馈网络,它对自注意力子层的输出进行进一步的处理,以增强模型的表示能力。

Python代码示例

编码器层(EncoderLayer)

class EncoderLayer(nn.Module):  
    def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1):  
        super(EncoderLayer, self).__init__()  
        self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)  
        self.linear1 = nn.Linear(d_model, dim_feedforward)  
        self.dropout = nn.Dropout(dropout)  
        self.linear2 = nn.Linear(dim_feedforward, d_model)  
  
        self.norm1 = nn.LayerNorm(d_model)  
        self.norm2 = nn.LayerNorm(d_model)  
        self.dropout1 = nn.Dropout(dropout)  
        self.dropout2 = nn.Dropout(dropout)  
  
        self.activation = nn.ReLU()  
  
    def forward(self, src):  
        src2 = self.norm1(src)  
        src = src + self.dropout1(self.self_attn(src2, src2, src2)[0])  
        src2 = self.norm2(src)  
        src = src + self.dropout2(self.linear2(self.dropout(self.activation(self.linear1(src2)))))  
        return src

编码器(Encoder)

class Encoder(nn.Module):  
    def __init__(self, layer, N):  
        super(Encoder, self).__init__()  
        self.layers = nn.ModuleList([layer for _ in range(N)])  
        self.norm = nn.LayerNorm(layer.self_attn.embed_dim)  
  
    def forward(self, src):  
        output = src  
        for mod in self.layers:  
            output = mod(output)  
        output = self.norm(output)  
        return output
3.7.3.3.2. 解码器(Decoder)
  1. 多层堆叠
    • 解码器同样由多个相同的解码器层堆叠而成。每个解码器层包含自注意力子层、编码器-解码器注意力子层、前馈神经网络子层以及残差连接和层归一化。
  2. 带掩码的自注意力子层
    • 解码器中的第一个自注意力子层是带掩码的,以防止在生成输出序列时看到未来的信息。掩码操作通常是将未来位置的注意力分数设置为负无穷大(或非常小的数),使得softmax函数将这些位置的注意力权重置为零。
  3. 编码器-解码器注意力子层
    • 编码器-解码器注意力子层负责将编码器的输出作为查询向量,与解码器中的键向量和值向量进行注意力计算。这样,解码器就能够根据编码器的输出生成相应的输出序列。
  4. 前馈神经网络子层
    • 与编码器中的前馈神经网络子层类似,解码器中的前馈神经网络子层对编码器-解码器注意力子层的输出进行进一步的处理。

Python代码示例

解码器层(DecoderLayer)

class DecoderLayer(nn.Module):  
    def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1):  
        super(DecoderLayer, self).__init__()  
        self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)  
        self.multihead_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)  
        self.linear1 = nn.Linear(d_model, dim_feedforward)  
        self.dropout = nn.Dropout(dropout)  
        self.linear2 = nn.Linear(dim_feedforward, d_model)  
  
        self.norm1 = nn.LayerNorm(d_model)  
        self.norm2 = nn.LayerNorm(d_model)  
        self.norm3 = nn.LayerNorm(d_model)  
        self.dropout1 = nn.Dropout(dropout)  
        self.dropout2 = nn.Dropout(dropout)  
        self.dropout3 = nn.Dropout(dropout)  
  
        self.activation = nn.ReLU()  
  
    def forward(self, tgt, memory, tgt_mask, memory_mask, tgt_key_padding_mask, memory_key_padding_mask):  
        tgt2 = self.norm1(tgt)  
        tgt = tgt + self.dropout1(self.self_attn(tgt2, tgt2, tgt2, attn_mask=tgt_mask, key_padding_mask=tgt_key_padding_mask)[0])  
        tgt2 = self.norm2(tgt)  
        tgt = tgt + self.dropout2(self.multihead_attn(tgt2, memory, memory, attn_mask=memory_mask, key_padding_mask=memory_key_padding_mask)[0])  
        tgt2 = self.norm3(tgt)  
        tgt = tgt + self.dropout3(self.linear2(self.dropout(self.activation(self.linear1(tgt2)))))  
        return tgt

解码器(Decoder)

class Decoder(nn.Module):  
    def __init__(self, layer, N):  
        super(Decoder, self).__init__()  
        self.layers = nn.ModuleList([layer for _ in range(N)])  
        self.norm = nn.LayerNorm(layer.self_attn.embed_dim)  
  
    def forward(self, tgt, memory, tgt_mask, memory_mask, tgt_key_padding_mask, memory_key_padding_mask):  
        output = tgt  
        for mod in self.layers:  
            output = mod(output, memory, tgt_mask, memory_mask, tgt_key_padding_mask, memory_key_padding_mask)  
        output = self.norm(output)  
        return output

在Transformer模型中,编码器和解码器的实现都依赖于nn.MultiheadAttention模块来处理自注意力和编码器-解码器注意力。前馈神经网络子层则是由两个线性层和一个ReLU激活函数组成。每个子层后面都接有残差连接和层归一化,以帮助模型在训练过程中保持稳定并提高泛化能力。

Transformer的运行原理基于自注意力机制和编码器-解码器架构。自注意力机制允许模型捕捉序列内部的依赖关系,而多头注意力机制则提高了模型的表示能力。编码器负责将输入序列编码为上下文表示,解码器则根据编码器的输出生成相应的输出序列。通过残差连接和层归一化等技术手段,Transformer模型能够在训练过程中保持稳定并提高泛化能力。

3.7.4. 优缺点

优点

  • 长距离依赖关系建模:通过自注意力机制,Transformer能够更好地捕捉长距离依赖关系。
  • 并行计算能力:多头注意力机制的并行计算极大提高了训练和推理的效率。
  • 通用性:不仅适用于NLP任务,还适用于图像处理、时间序列分析等其他领域。

缺点

  • 高计算成本:模型的复杂性导致在训练和推理过程中需要大量的计算资源。
  • 优化难度:模型的复杂性和超参数的数量增加了优化的难度。
  • 对长文本处理挑战:在处理长文本时,由于位置编码和注意力机制的限制,可能受到内存限制和效率影响。

3.7.5. 在游戏AI中的应用、场景和典型应用实例

3.7.5.1. 应用与场景
  • 策略游戏:Transformer可用于分析游戏状态,预测对手行为,制定最优策略。通过处理游戏中的序列数据(如历史动作、资源分布等),Transformer能够捕捉长距离依赖关系,提高策略制定的准确性。
  • 实时对战游戏:在实时对战游戏中,Transformer可用于实时分析游戏画面和对手行为,快速做出反应。通过结合图像处理和自然语言处理技术,Transformer可以实现对游戏画面的深度理解和对手意图的准确预测。
3.7.5.2. 典型应用实例
  • 星际争霸2的AlphaStar:AlphaStar,DeepMind开发的人工智能。AlphaStar学会了玩《星际争霸II》,在所有三场比赛中都被评为大师级,在官方的人类玩家排名中排名前99.8%以上。2019年发表于《自然》。虽然AlphaStar主要基于深度强化学习(DRL)和蒙特卡洛树搜索(MCTS),但Transformer模型在其中可能用于处理和分析游戏录像、学习人类玩家的策略和技巧。通过自注意力机制,AlphaStar能够捕捉游戏中的长距离依赖关系,提高策略制定的深度和广度。

3.7.5.3. AlphaStar类似实现简单示例代码

实现一个类似于星际争霸2的AlphaStar的AI系统是一个庞大且复杂的工程,涉及到深度学习和强化学习的多个方面。AlphaStar使用深度神经网络和强化学习技术来玩游戏,具体技术包括但不限于深度学习模型(如卷积神经网络)、蒙特卡洛树搜索(MCTS)和序列模型等。

下面是一个非常简化的Python示例,用于说明如何实现一个基于强化学习的智能体,虽然它远远不能达到AlphaStar的复杂度。

第一步,你需要安装一些必要的库,比如Gym和tensorflowpytorch。这里我们假设使用tensorflow

pip install tensorflow gym

第二步,以下是一个使用TensorFlow和Keras实现的简单DQN(深度Q网络)模型,用于训练一个智能体在Gym环境中的CartPole游戏上玩:

import numpy as np  
import random  
import tensorflow as tf  
from collections import deque  
from tensorflow.keras.models import Sequential  
from tensorflow.keras.layers import Dense  
from tensorflow.keras.optimizers import Adam  
from gym import make  
  
class DQN:  
    def __init__(self, state_size, action_size):  
        self.state_size = state_size  
        self.action_size = action_size  
        self.memory = deque(maxlen=2000)  
        self.gamma = 0.95  # discount rate  
        self.epsilon = 1.0  # exploration rate  
        self.epsilon_min = 0.01  
        self.epsilon_decay = 0.995  
        self.learning_rate = 0.001  
        self.model = self._build_model()  
  
    def _build_model(self):  
        model = Sequential()  
        model.add(Dense(24, input_dim=self.state_size, activation='relu'))  
        model.add(Dense(24, activation='relu'))  
        model.add(Dense(self.action_size, activation='linear'))  
        model.compile(loss='mse', optimizer=Adam(lr=self.learning_rate))  
        return model  
  
    def remember(self, state, action, reward, next_state, done):  
        self.memory.append((state, action, reward, next_state, done))  
  
    def act(self, state):  
        if np.random.rand() <= self.epsilon:  
            return random.randrange(self.action_size)  
        act_values = self.model(state)  
        return np.argmax(act_values[0])  
  
    def replay(self, batch_size):  
        minibatch = random.sample(self.memory, batch_size)  
        for state, action, reward, next_state, done in minibatch:  
            target = reward  
            if not done:  
                target = (reward + self.gamma * np.amax(self.model.predict(next_state)[0]))  
            target_f = self.model.predict(state)  
            target_f[0][action] = target  
            self.model.fit(state, target_f, epochs=1, verbose=0)  
        if self.epsilon > self.epsilon_min:  
            self.epsilon *= self.epsilon_decay  
  
env = make('CartPole-v1')  
state_size = env.observation_space.shape[0]  
action_size = env.action_space.n  
agent = DQN(state_size, action_size)  
  
# 训练智能体  
episodes = 1000  
  
for e in range(episodes):  
    state = env.reset()  
    state = np.reshape(state, [1, state_size])  
    for time_t in range(500):  
        action = agent.act(state)  
        next_state, reward, done, _ = env.step(action)  
        reward = reward if not done else -10  
        next_state = np.reshape(next_state, [1, state_size])  
        agent.remember(state, action, reward, next_state, done)  
        state = next_state  
        if done:  
            print("episode: {}/{}, score: {}, e: {:.2}"  
                  .format(e, episodes, time_t, agent.epsilon))  
            break  
        if len(agent.memory) > batch_size:  
            agent.replay(32)

这段代码创建了一个简单的DQN智能体,用于在CartPole环境中学习如何玩游戏。AlphaStar的实现远比这复杂,涉及到更多的技术和计算资源,但这个例子可以作为开始探索深度学习和强化学习在游戏AI中应用的一个起点哦。

3.7.6. 小小总结下

Transformer算法以其独特的自注意力机制和编码器-解码器架构在自然语言处理领域取得了巨大成功,并逐渐扩展到图像处理、时间序列分析等其他领域。

在游戏AI中,Transformer的应用潜力巨大,有望为策略制定和实时对战提供新的解决方案。

关于Transformer算法的内容,限于篇幅太长,内容太多,后面有机会时慢慢增加更多的内容

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度学习经典检测方法概述

一、深度学习经典检测方法 two-stage&#xff08;两阶段&#xff09;&#xff1a;Faster-rcnn Mask-Rcnn系列 one-stage&#xff08;单阶段&#xff09;&#xff1a;YOLO系列 1. one-stage 最核心的优势&#xff1a;速度非常快&#xff0c;适合做实时检测任务&#xff01; 但是…

【知识图谱系列】(实例)python操作neo4j构建企业间的业务往来的知识图谱

本章节通过聚焦于"金额"这一核心属性,构建了一幅知识图谱,旨在揭示"销售方"与"购买方"间的商业互动网。在这张图谱中,绿色节点象征着购买方,而红色节点则代表了销售方。这两类节点间的紧密连线,不仅映射了双方在市场活动中的合作桥梁,还特…

8个成功的原型设计案例分享

原型设计在整个产品设计过程中非常的重要&#xff0c;定下了整个产品的基调&#xff0c;想要做好原型设计&#xff0c;需要不断的经验的积累&#xff0c;新手入门最快的方式就是学习一些优秀的原型设计案例&#xff0c;今天就为大家分享一些可以直接使用源文件进行编辑和修改的…

Linux高级编程——线程

pthread 线程 概念 &#xff1a;线程是轻量级进程&#xff0c;一般是一个进程中的多个任务。 进程是系统中最小的资源分配单位. 线程是系统中最小的执行单位。 优点&#xff1a; 比多进程节省资源&#xff0c;可以共享变量 进程会占用&am…

SpringBoot(二)SpringBoot多环境配置

Spring框架常用注解简单介绍 SpringMVC常用注解简单介绍 SpringBoot&#xff08;一&#xff09;创建一个简单的SpringBoot工程 SpringBoot&#xff08;二&#xff09;SpringBoot多环境配置 SpringBoot&#xff08;三&#xff09;SpringBoot整合MyBatis SpringBoot&#xff08;四…

MySQL高级-SQL优化- limit优化(覆盖索引加子查询)

文章目录 0、limit 优化0.1、从表 tb_sku 中按照 id 列进行排序&#xff0c;然后跳过前 9000000 条记录0.2、通过子查询获取按照 id 排序后的第 9000000 条开始的 10 条记录的 id 值&#xff0c;然后在原表中根据这些 id 值获取对应的完整记录 1、上传5个sql文件到 /root2、查看…

AI与学术的交响:ChatGPT辅助下的实验设计新篇章

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 在学术研究中&#xff0c;实验设计是确保研究质量和结果可信度的关键环节。这篇文章我们将为大家介绍如何利用ChatGPT辅助完成学术论文的实验设计&#xff0c;通过提供灵感、优化实验步…

有什么好用的ai自动绘画软件?6个软件帮助你快速进行智能绘画

有什么好用的ai自动绘画软件&#xff1f;6个软件帮助你快速进行智能绘画 寻找好用的AI自动绘画软件可以帮助用户快速进行智能绘画&#xff0c;以下是几款推荐的软件&#xff0c;它们能够提供不同风格和功能的绘画体验&#xff1a; 聪明灵犀&#xff1a;这是一款知名的AI艺术应…

【pytorch10】统计属性

常见统计属性 norm&#xff08;范数&#xff09;mean,sumprodmax&#xff0c;min&#xff0c;argmin&#xff0c;argmaxkthvalue&#xff0c;topk kthvalue求第几个的位置和第几个的值 topk求top几的这样的一个数值 norm范数 这里的norm表达的是范数的意思&#xff0c;norma…

多地高温持续“热力”爆表 约克VRF中央空调带你清凉舒爽一夏

“出门5分钟&#xff0c;流汗2小时”,夏季高温天气&#xff0c;怎一个“热”字了得&#xff1f;6月以来&#xff0c;我国多地迎来高温“炙烤”&#xff0c;全国出现40℃以上高温的范围持续增加&#xff0c;随着中央气象台高温预警持续拉响&#xff0c;人们都很纳闷&#xff1a;…

主流电商平台API接口(天猫获得淘宝商品详情,获得淘宝app商品详情原数据 ,获得淘口令真实url API,按图搜索淘宝商品(拍立淘) API )

主流电商平台商品接口在电商企业中具有重要应用价值。通过商品接口&#xff0c;电商企业可以实现商品同步功能&#xff1a; 商品信息同步&#xff1a;通过接口可以实时同步主流电商平台上的商品信息&#xff0c;包括商品标题、价格、库存、销量等数据&#xff0c;确保企业在自…

[leetcode]search-insert-position 搜索插入位置

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int searchInsert(vector<int>& nums, int target) {int left 0, right nums.size()-1;while(left <right) {int mid left (right-left)/2;if(nums[mid] target){return mid;} else if(nu…

subline设置打开文件重启一个新的窗口

问题 打开文件后&#xff0c;用的是同一个窗口的子tab页面 想要打开一个新的窗口 解决 点解preferences->setting 在右边的配置文件新增一行 “open_files_in_new_window”: “always” 保存 搞定&#xff01;

立创ESP32C3学习笔记

好的设计可以学到很多知识和细节&#xff0c;就如同学会一个数学知识点最好的方法是做典型例题。 乐鑫关于产品的硬件设计都有硬件设计指南&#xff0c;设计板子的时候需要仔细阅读&#xff1a; 原理图设计 - ESP32-C3 - — ESP 硬件设计指南 latest 文档 (espressif.com) 技…

IP地址查询和代理服务器:双重保护隐私

随着网络应用的日益普及&#xff0c;我们的个人信息和数据安全面临前所未有的挑战。在此背景下&#xff0c;IP地址查询和代理服务器成为保护个人隐私和网络安全的两大关键工具。本文将从IP地址查询的原理和应用出发&#xff0c;深入剖析代理服务器在网络隐私保护中的作用&#…

JS(JavaScript)事件处理(事件绑定)趣味案例

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

5. Spring IoCDI ★ ✔

5. Spring IoC&DI 1. IoC & DI ⼊⻔1.1 Spring 是什么&#xff1f;★ &#xff08;Spring 是包含了众多⼯具⽅法的 IoC 容器&#xff09;1.1.1 什么是容器&#xff1f;1.1.2 什么是 IoC&#xff1f;★ &#xff08;IoC: Inversion of Control (控制反转)&#xff09;总…

分布式kettle调度管理平台简介

介绍 Kettle&#xff08;也称为Pentaho Data Integration&#xff09;是一款开源的ETL&#xff08;Extract, Transform, Load&#xff09;工具&#xff0c;由Pentaho&#xff08;现为Hitachi Vantara&#xff09;开发和维护。它提供了一套强大的数据集成和转换功能&#xff0c…

第二十课,认识列表与定义列表

一&#xff0c;列表的作用 思考一个问题&#xff1a;如果我想要在程序中&#xff0c;记录5名学生的信息&#xff0c;如姓名。 如何做呢&#xff1f; 这就是列表的作用&#xff0c;能帮助我们更加高效的存储各种数据 思考&#xff1a;如果一个班级100位学生&#xff0c;每个人…

毅速丨金属3D打印是制造业转型升级的重要技术

随着科技的进步&#xff0c;金属3D打印技术已成为制造业升级的重要驱动力。它以其独特的优势&#xff0c;正引领着制造业迈向新的未来。 金属3D打印技术的突破&#xff1a; 设计自由。金属3D打印能制造任意形状和结构的零件&#xff0c;为设计师提供了无限的创意空间。 快速制…