Huggingface中Transformer模型使用

一、Huggingface介绍

1、Huggingface定位

NLP自从Transformer模型出现后,处理方式有大统一的趋势,首先回答几个基础问题:

1、自然语言处理究竟要做一件什么事呢?自然语言处理最终解决的是分类问题,但是它不仅仅输出一个分类的预测结果,关键的在于构建一个聪明的模型,不光能学习不同数据集的问题,还能处理不同类别的问题。

2、如何培养模型的学习能力?自然语言处理就像我们读书一样,要训练它的阅读能力、学习能力、理解能力,给出的是一系列阅读材料,然后想办法让它理解语言,不仅仅是一个分类的专项技能,这里就涉及到注意力机制了,通过设置学习任务每一段只关注其中部分语料,并分配好权重,通过训练得到比较好的效果。之后基于注意力模型搭建复杂的神经网络,以获取强大的学习能力。

3、NLP中的核心门派:BERT系(五岳剑派),GPT系(魔教),BERT有点像做完形填空,GPT有点像写小作文。现在NLP已到了大模型时代,已经在拼海量的数据量和参数,目前GPT系列已经取得很大成功,但是是大模型,个人要训练很是很麻烦的,也有些开源的大模型,先从调优做起!

4、如何开始NLP呢?引出这个问题,也是Huggingface的关键理念了,历史上有很多NLP的算法,但是实事已经证明大部分没啥用,有用的就是Transformer这一系列的模型了,而Huggingface就是集大成者于一身,包括了当下NLP所有核心模型,只需要一行代码就可以调用BERT模型,GPT模型及其训练好的权重参数!其次,Huggingface它不仅是一个工具包,更是一个社区,也是NLP大佬们的舞台。当然kaggle也是个不错的平台,结合着用!

2、Huggingface调用示例

Huggingface这个包基本调用即可,先安装包pip install:

pip install transformers

开箱即用,方便:

import warnings
warnings.filterwarnings("ignore")
from transformers import pipeline#用人家设计好的流程完成一些简单的任务
classifier = pipeline("sentiment-analysis")
classifier(
    [
        "I've been waiting for a HuggingFace course my whole life.",
        "I hate this so much!",
    ]
)

结果:

[{'label': 'POSITIVE', 'score': 0.9598049521446228},
 {'label': 'NEGATIVE', 'score': 0.9994558691978455}]

测试很方便,如果有包不好下载,找镜像、先download安装包之后再安装。

二、Transformer模型

1、注意力机制(Attention model)

Transformer可以说大名鼎鼎了,NLP领域大哥大级别,一统天下好多年了,而且是CV界新秀,开场即巅峰。它的基础在于注意力机制,先来吴恩达老师对Transformer细节的架构图:

可以看出Transformer有Encoder、Decoder两部分组成,采用Multi-Head Attention(多头注意力)提取文本特征,形成编码器,最终也通过两层Multi-Head Attention进行解码,Transformer核心就是Attention Model

什么是注意力?注意力是稀缺的,而环境中信息量非常之大,比如人类的视觉神经每秒收到10^{8}位的信息,圆圆超过大脑的处理能力,但人类从远古祖先中继承了一项本能经验“并非感官的所有输入都是一样的”,大脑会将关注点集中在一小部分信息中,这便是注意力。认知觉醒中提到一种凭感觉学习的方法,核心思路便是先用感性能力帮助自己选择,再用理性能力帮助自己思考。这个过程中凭感觉学习中的感觉就类似于注意力,注意力模型就是通过训练找到潜意识里的感觉,分别出重要的信息!

回到注意力模型,源于机器翻译,并快速推广到了其他应用领域,有三个重要概念:查询(query)、键(key)和值(value)。查询相当于自主性提示,触发感觉得信息,比如突然看到学校的照片,回想起求学经历,query相当于这张照片,键和值的理解要花点时间,键相当于概述求学经历,值相当于求学经历的细节,在哪个教室听哪位老师讲课等等。

回到NLP中,用这幅图好理解Attention在做什么(这里是自注意力模型,query就是语料自身):

三、调用流程概述

首先原始文本用Tokenizer进行分词处理得到输入的文本,然后通过模型进行学习,学习之后进行处理、预测分析。而且huggingface有个好处,分词器、数据集、模型都封装好了!很方便。

1、Tokenizer

Tokenizer会做3件事:

  • 分词,分字以及特殊字符(起始,终止,间隔,分类等特殊字符可以自己设计的)
  • 对每一个token映射得到一个ID(每个词都会对应一个唯一的ID)
  • 还有一些辅助信息也可以得到,比如当前词属于哪个句子(还有一些MASK,表示是否是原来的词还是特殊字符等)

其中AutoTokenizer可以自动根据模型来判断采用哪个分词器:

from transformers import AutoTokenizer#自动判断

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"#根据这个模型所对应的来加载
tokenizer = AutoTokenizer.from_pretrained(checkpoint)

输入文本:

raw_inputs = [
    "I've been waiting for a this course my whole life.",
    "I hate this so much!",
]
inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt")
print(inputs)

打印结果(得到两个字典映射,'input_ids',一个tensor集合,每个词所对应的ID集合;attention_mask,一个tensor集合,表示是否是原来的词还是特殊字符等):

{'input_ids': tensor([[ 101, 1045, 1005, 2310, 2042, 3403, 2005, 1037, 2023, 2607, 2026, 2878,
         2166, 1012,  102],
        [ 101, 1045, 5223, 2023, 2061, 2172,  999,  102,    0,    0,    0,    0,
            0,    0,    0]]), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]])}

如果想根据id重新获得原始句子,如下操作:

tokenizer.decode([ 101, 1045, 1005, 2310, 2042, 3403, 2005, 1037, 2023, 2607, 2026, 2878,2166, 1012,  102])

生成的文本会存在特殊字符,这些特殊字符是因为人家模型训练的时候就加入了这个东西,所以这里默认也加入了(google系的处理)

"[CLS] i've been waiting for a this course my whole life. [SEP]"

2、模型的加载

模型的加载直接指定好名字即可(先不加输出层)

from transformers import AutoModel

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
model = AutoModel.from_pretrained(checkpoint)
model

打印出来模型架构,就是DistilBertModel的架构了,能看到embeddings层、transformer层,看得还比较清晰:

DistilBertModel(
  (embeddings): Embeddings(
    (word_embeddings): Embedding(30522, 768, padding_idx=0)
    (position_embeddings): Embedding(512, 768)
    (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
    (dropout): Dropout(p=0.1, inplace=False)
  )
  (transformer): Transformer(
    (layer): ModuleList(
      (0): TransformerBlock(
        (attention): MultiHeadSelfAttention(
          (dropout): Dropout(p=0.1, inplace=False)
          (q_lin): Linear(in_features=768, out_features=768, bias=True)
          (k_lin): Linear(in_features=768, out_features=768, bias=True)
          (v_lin): Linear(in_features=768, out_features=768, bias=True)
          (out_lin): Linear(in_features=768, out_features=768, bias=True)
        )
        (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
        (ffn): FFN(
          (dropout): Dropout(p=0.1, inplace=False)
          (lin1): Linear(in_features=768, out_features=3072, bias=True)
          (lin2): Linear(in_features=3072, out_features=768, bias=True)
        )
        (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
      )
      (1): TransformerBlock(
        (attention): MultiHeadSelfAttention(
          (dropout): Dropout(p=0.1, inplace=False)
          (q_lin): Linear(in_features=768, out_features=768, bias=True)
          (k_lin): Linear(in_features=768, out_features=768, bias=True)
          (v_lin): Linear(in_features=768, out_features=768, bias=True)
          (out_lin): Linear(in_features=768, out_features=768, bias=True)
        )
        (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
        (ffn): FFN(
          (dropout): Dropout(p=0.1, inplace=False)
          (lin1): Linear(in_features=768, out_features=3072, bias=True)
          (lin2): Linear(in_features=3072, out_features=768, bias=True)
        )
        (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
      )
      (2): TransformerBlock(
        (attention): MultiHeadSelfAttention(
          (dropout): Dropout(p=0.1, inplace=False)
          (q_lin): Linear(in_features=768, out_features=768, bias=True)
          (k_lin): Linear(in_features=768, out_features=768, bias=True)
          (v_lin): Linear(in_features=768, out_features=768, bias=True)
          (out_lin): Linear(in_features=768, out_features=768, bias=True)
        )
        (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
        (ffn): FFN(
          (dropout): Dropout(p=0.1, inplace=False)
          (lin1): Linear(in_features=768, out_features=3072, bias=True)
          (lin2): Linear(in_features=3072, out_features=768, bias=True)
        )
        (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
      )
      (3): TransformerBlock(
        (attention): MultiHeadSelfAttention(
          (dropout): Dropout(p=0.1, inplace=False)
          (q_lin): Linear(in_features=768, out_features=768, bias=True)
          (k_lin): Linear(in_features=768, out_features=768, bias=True)
          (v_lin): Linear(in_features=768, out_features=768, bias=True)
          (out_lin): Linear(in_features=768, out_features=768, bias=True)
        )
        (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
        (ffn): FFN(
          (dropout): Dropout(p=0.1, inplace=False)
          (lin1): Linear(in_features=768, out_features=3072, bias=True)
          (lin2): Linear(in_features=3072, out_features=768, bias=True)
        )
        (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
      )
      (4): TransformerBlock(
        (attention): MultiHeadSelfAttention(
          (dropout): Dropout(p=0.1, inplace=False)
          (q_lin): Linear(in_features=768, out_features=768, bias=True)
          (k_lin): Linear(in_features=768, out_features=768, bias=True)
          (v_lin): Linear(in_features=768, out_features=768, bias=True)
          (out_lin): Linear(in_features=768, out_features=768, bias=True)
        )
        (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
        (ffn): FFN(
          (dropout): Dropout(p=0.1, inplace=False)
          (lin1): Linear(in_features=768, out_features=3072, bias=True)
          (lin2): Linear(in_features=3072, out_features=768, bias=True)
        )
        (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
      )
      (5): TransformerBlock(
        (attention): MultiHeadSelfAttention(
          (dropout): Dropout(p=0.1, inplace=False)
          (q_lin): Linear(in_features=768, out_features=768, bias=True)
          (k_lin): Linear(in_features=768, out_features=768, bias=True)
          (v_lin): Linear(in_features=768, out_features=768, bias=True)
          (out_lin): Linear(in_features=768, out_features=768, bias=True)
        )
        (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
        (ffn): FFN(
          (dropout): Dropout(p=0.1, inplace=False)
          (lin1): Linear(in_features=768, out_features=3072, bias=True)
          (lin2): Linear(in_features=3072, out_features=768, bias=True)
        )
        (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
      )
    )
  )
)

看下输出层的结构,这里**表示分配字典,按照参数顺序依次赋值:

outputs = model(**inputs)
print(outputs.last_hidden_state.shape)
torch.Size([2, 15, 768])

3、模型基本逻辑

根据上面代码总结模型的逻辑:input——>词嵌入——>Transformer——>隐藏层——>Head层。

4、加入输出头

from transformers import AutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)
outputs = model(**inputs)
print(outputs.logits.shape)

这里就得到分类后的结果:

torch.Size([2, 2])

再来看看模型的结构:

model
DistilBertForSequenceClassification(
  (distilbert): DistilBertModel(
    (embeddings): Embeddings(
      (word_embeddings): Embedding(30522, 768, padding_idx=0)
      (position_embeddings): Embedding(512, 768)
      (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
      (dropout): Dropout(p=0.1, inplace=False)
    )
    (transformer): Transformer(
      (layer): ModuleList(
        (0): TransformerBlock(
          (attention): MultiHeadSelfAttention(
            (dropout): Dropout(p=0.1, inplace=False)
            (q_lin): Linear(in_features=768, out_features=768, bias=True)
            (k_lin): Linear(in_features=768, out_features=768, bias=True)
            (v_lin): Linear(in_features=768, out_features=768, bias=True)
            (out_lin): Linear(in_features=768, out_features=768, bias=True)
          )
          (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
          (ffn): FFN(
            (dropout): Dropout(p=0.1, inplace=False)
            (lin1): Linear(in_features=768, out_features=3072, bias=True)
            (lin2): Linear(in_features=3072, out_features=768, bias=True)
          )
          (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
        )
        (1): TransformerBlock(
          (attention): MultiHeadSelfAttention(
            (dropout): Dropout(p=0.1, inplace=False)
            (q_lin): Linear(in_features=768, out_features=768, bias=True)
            (k_lin): Linear(in_features=768, out_features=768, bias=True)
            (v_lin): Linear(in_features=768, out_features=768, bias=True)
            (out_lin): Linear(in_features=768, out_features=768, bias=True)
          )
          (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
          (ffn): FFN(
            (dropout): Dropout(p=0.1, inplace=False)
            (lin1): Linear(in_features=768, out_features=3072, bias=True)
            (lin2): Linear(in_features=3072, out_features=768, bias=True)
          )
          (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
        )
        (2): TransformerBlock(
          (attention): MultiHeadSelfAttention(
            (dropout): Dropout(p=0.1, inplace=False)
            (q_lin): Linear(in_features=768, out_features=768, bias=True)
            (k_lin): Linear(in_features=768, out_features=768, bias=True)
            (v_lin): Linear(in_features=768, out_features=768, bias=True)
            (out_lin): Linear(in_features=768, out_features=768, bias=True)
          )
          (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
          (ffn): FFN(
            (dropout): Dropout(p=0.1, inplace=False)
            (lin1): Linear(in_features=768, out_features=3072, bias=True)
            (lin2): Linear(in_features=3072, out_features=768, bias=True)
          )
          (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
        )
        (3): TransformerBlock(
          (attention): MultiHeadSelfAttention(
            (dropout): Dropout(p=0.1, inplace=False)
            (q_lin): Linear(in_features=768, out_features=768, bias=True)
            (k_lin): Linear(in_features=768, out_features=768, bias=True)
            (v_lin): Linear(in_features=768, out_features=768, bias=True)
            (out_lin): Linear(in_features=768, out_features=768, bias=True)
          )
          (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
          (ffn): FFN(
            (dropout): Dropout(p=0.1, inplace=False)
            (lin1): Linear(in_features=768, out_features=3072, bias=True)
            (lin2): Linear(in_features=3072, out_features=768, bias=True)
          )
          (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
        )
        (4): TransformerBlock(
          (attention): MultiHeadSelfAttention(
            (dropout): Dropout(p=0.1, inplace=False)
            (q_lin): Linear(in_features=768, out_features=768, bias=True)
            (k_lin): Linear(in_features=768, out_features=768, bias=True)
            (v_lin): Linear(in_features=768, out_features=768, bias=True)
            (out_lin): Linear(in_features=768, out_features=768, bias=True)
          )
          (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
          (ffn): FFN(
            (dropout): Dropout(p=0.1, inplace=False)
            (lin1): Linear(in_features=768, out_features=3072, bias=True)
            (lin2): Linear(in_features=3072, out_features=768, bias=True)
          )
          (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
        )
        (5): TransformerBlock(
          (attention): MultiHeadSelfAttention(
            (dropout): Dropout(p=0.1, inplace=False)
            (q_lin): Linear(in_features=768, out_features=768, bias=True)
            (k_lin): Linear(in_features=768, out_features=768, bias=True)
            (v_lin): Linear(in_features=768, out_features=768, bias=True)
            (out_lin): Linear(in_features=768, out_features=768, bias=True)
          )
          (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
          (ffn): FFN(
            (dropout): Dropout(p=0.1, inplace=False)
            (lin1): Linear(in_features=768, out_features=3072, bias=True)
            (lin2): Linear(in_features=3072, out_features=768, bias=True)
          )
          (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
        )
      )
    )
  )
  (pre_classifier): Linear(in_features=768, out_features=768, bias=True)
  (classifier): Linear(in_features=768, out_features=2, bias=True)
  (dropout): Dropout(p=0.2, inplace=False)
)

之后采用softmax进行预测:

import torch

predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
print(predictions)
tensor([[1.5446e-02, 9.8455e-01],
        [9.9946e-01, 5.4418e-04]], grad_fn=<SoftmaxBackward0>)

id2label这个我们后续可以自己设计,标签名字对应都可以自己指定:

model.config.id2label
{0: 'NEGATIVE', 1: 'POSITIVE'}

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

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

相关文章

算法之二分查找算法

二分查找算法简介 1. 首先说明二分查找算法是比较恶心, 细节很多, 很容易写出死循环的算法, 但熟悉了之后是最简单的算法. 2. 其次我们可能听说过二分查找的前提是数组有序的前提下进行, 但其实不一定. 3. 二分查找算法有一套模板: 朴素的二分模板: 比较简单, 但是有局限性查找…

运维自动化之ansible

pxe 一键安装操作系统 操作系统只是提供一个平台 lnmp 需要多软件协同完成的一个简单项目 服务器正常运行 日常运维 巡检 服务器上的软件正常运行 zabbix 普罗米修斯 系统调优&#xff0c;架构调优 云计算核心职能 搭建平台架构 日常运营保障 性能效率优化 相关工具 代…

SDWAN专线对企业接入有门槛吗

SD-WAN&#xff08;软件定义广域网&#xff09;技术作为一种新型的网络解决方案&#xff0c;正在成为企业网络接入的热门选择。然而&#xff0c;对于企业来说&#xff0c;接入SD-WAN专线是否存在门槛&#xff0c;是一个值得探讨的问题。本文将从不同角度分析SD-WAN专线对企业接…

HTML 学习笔记(十一)表单

一、分块 1.单行文本框控件–文本框和密码框 文本框控件通过单标签input实现&#xff0c;其具有必要属性type来控制输入控件的类型(默认为text即文本信息)&#xff0c;密码框的type为password(口令)。   表单的动作属性定义了目的文件的文件名。由动作属性定义的这个文件通常…

国内可用免费AI工具集

1、Kimi Chat 由月之暗面科技有限公司&#xff08;Moonshot AI&#xff09;开发的人工智能助手。擅长中英文对话&#xff0c;能够提供安全、有帮助且准确的回答。它的能力包括阅读和理解用户上传的文件&#xff0c;访问互联网内容&#xff0c;以及结合搜索结果来回答问题。比如…

【C#】WPF获取屏幕分辨率

SystemParameters提供的接口&#xff0c;其实是获取渲染过程中的实际高宽&#xff0c;是受系统DPI设置的影响。 以 1920 * 1080 和 125% DPI为例&#xff1a; 分辨率高度&#xff1a;1080&#xff0c;实际获取的高度为&#xff1a;864。 分辨率宽度&#xff1a;1920&#xff…

高项-项目整合管理

项目整合管理的目标 资源分配平衡竞争性需求研究各种备选方法裁剪过程以实现项目目标管理各个项目管理知识域之间的依赖关系 项目整合管理的过程 制定项目章程制定项目管理计划指导与管理项目工作管理项目知识监控项目工作实施整体变更控制结束项目或阶段 七个过程和五大过…

【1688运营】如何拆解竞争对手店铺和单品数据?

关注竞争对手数据是1688运营中不可或缺的一环&#xff0c;它有助于企业更好地了解市场环境、发现市场机会、学习成功经验、预测市场变化以及提升竞争力。以下是一些建议&#xff0c;帮助你全面、深入地分析竞争对手的店铺和单品数据&#xff1a; 1、监控店铺数据 可以通过店雷…

求第n个斐波那契数--c语言

用递归的方法&#xff1a; //用递归求第n个斐波那契数 int fib(int n){if(n<2){return 1;}else{return fib(n-1)fib(n-2); } } #include<stdio.h> int main(){int n0;printf("请输入n的值&#xff1a;");scanf("%d",&n);int result fib(n);…

未来艺术展览新趋势——3D线上画展如何创新展示?

一、艺术展示的数字化转型 随着科技的不断进步&#xff0c;3D线上画展作为艺术展示的新趋势&#xff0c;正逐渐改变着人们欣赏和购买艺术作品的方式。对于画家而言&#xff0c;3D线上画展不仅提供了一个全新的平台来展示他们的作品&#xff0c;还开辟了销售渠道&#xff0c;扩大…

面向对象技术(第一周)

目录 ⚽前言 &#x1f3d0;面向对象思想 起源 现实 编程联系 面向对象思想总结 &#x1f3c0;面向对象开发方法 开发中的名词&#xff1a; 名词间的关系 名词具体阐释 一、对象 二、消息和方法&#xff1a; 前言 本文所有知识点和内容均来自山东大学潘丽老师及山东…

京津冀协同发展:北京·光子1号金融算力中心——智能科技新高地

京津冀协同发展是党中央在新的历史条件下提出的一项重大国家战略&#xff0c;对于全面推进“五位一体”总体布局&#xff0c;以中国式现代化全面推进强国建设、民族复兴伟业&#xff0c;具有重大现实意义和深远历史意义。随着京津冀协同发展战略的深入推进&#xff0c;区域一体…

unique_ptr使用说明

背景 指针问题一直是一个比较麻烦的事情&#xff0c;比如很多人说要用智能指针完全替换掉裸指针&#xff0c;有人说要用unique_ptr, 有人建议shared_ptr,可是实际看各种经典框架&#xff0c;发现一个框架什么指针都有&#xff0c;使用的方法也是无法八门&#xff0c;这里简单说…

可访问性使命:Facebook构建无障碍社交空间

在当今数字化时代&#xff0c;社交媒体已成为人们日常生活的重要组成部分&#xff0c;而Facebook作为全球最大的社交平台之一&#xff0c;其使命不仅在于连接世界&#xff0c;还在于构建一个无障碍的社交空间&#xff0c;让每个人都能参与其中。本文将深入探讨Facebook在可访问…

几个增强诊断详解

几个增强诊断 基于CAN线 ISO15031-5是排放相关的应用层协议&#xff0c;它不关心我们使用K线还是CAN线&#xff0c;主要用于监控车辆基本参数&#xff0c;例如监控里程、车速&#xff1b;用于监控排放相关的参数&#xff0c;比如各种尾气的含量&#xff0c;氧含量等等&#xf…

红队笔记7--Web机器为Linuxdocker逃逸

其实&#xff0c;不知道大家有没有想过&#xff0c;我们之前练习的都是web机器是windows的版本&#xff0c;但是其实&#xff0c;在现实生活中&#xff0c;服务器一般都是Linux的版本&#xff0c;根本不可能用到windows的版本 那么如果是Linux的话&#xff0c;我们就有很多的困…

【正点原子STM32探索者】CubeMX+Keil开发环境搭建

文章目录 一、简单开箱二、资料下载三、环境搭建3.1 安装Keil MDK3.2 激活Keil MDK3.3 安装STM32CubeMX3.4 安装STM32F4系列MCU的Keil支持包 四、GPIO点灯4.1 查阅开发板原理图4.2 创建STM32CubeMX项目4.3 配置系统时钟和引脚功能4.4 生成Keil项目4.5 打开Keil项目4.6 编译Keil…

K8s的kubeadm方式部署集群实例

目录 一、准备环境 主机清单 修改主机名 设置防火墙、selinux状态 主机名解析 固定ip 重启网卡 同步时间 关闭swap分区 二、获取镜像 三、安装docker 四、配置kubeadm源 安装依赖包及常用插件 1.配置kubeadm源&#xff0c;安装对应版本 2.加载相关ipvs模块 3.配…

Day17:开发流程、开发社区首页、项目的调试、版本控制

开发流程 一次请求过程 先开发DAO&#xff0c;再开发service&#xff0c;再开发controller 开发社区首页的分布实现 显示前10个帖子 创建帖子数据表 CREATE TABLE discuss_post (id int NOT NULL AUTO_INCREMENT,user_id varchar(45) DEFAULT NULL,title varchar(100) DEF…

使用Java的等待/通知机制实现一个简单的阻塞队列

Java的等待/通知机制 Java的等待通知机制是多线程间进行通信的一种方式。 有三个重要的方法&#xff1a;wait()&#xff0c;notify() 和以及notifyAll() wait()&#xff1a;该方法用于让当前线程&#xff08;即调用该方法的线程&#xff09;进入等待状态并且释放掉该对象上的…