昇思MindSpore学习笔记5-02生成式--RNN实现情感分类

摘要:

        记录MindSpore AI框架使用RNN网络对自然语言进行情感分类的过程、步骤和方法。

        包括环境准备、下载数据集、数据集加载和预处理、构建模型、模型训练、模型测试等。

一、

情感分类。

RNN网络模型

实现效果:

        输入: This film is terrible

        正确标签: Negative

        预测标签: Negative

        输入: This film is great

        正确标签: Positive

        预测标签: Positive

二、环境准备

%%capture captured_output
# 实验环境已经预装了mindspore==2.2.14,如需更换mindspore版本,可更改下面mindspore的版本号
!pip uninstall mindspore -y
!pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore==2.2.14
# 查看当前 mindspore 版本
!pip show mindspore

输出:

Name: mindspore
Version: 2.2.14
Summary: MindSpore is a new open source deep learning training/inference framework that could be used for mobile, edge and cloud scenarios.
Home-page: https://www.mindspore.cn
Author: The MindSpore Authors
Author-email: contact@mindspore.cn
License: Apache 2.0
Location: /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages
Requires: asttokens, astunparse, numpy, packaging, pillow, protobuf, psutil, scipy
Required-by: 

手动安装tqdm和requests库

!pip install tqdm requests

三、加载数据

IMDB影评数据集

        Positive

        Negative

预训练词向量

        编码自然语言单词

        获取文本语义特征

选取Glove词向量作为Embedding。

1.下载数据集和预训练词向量

requests库

        http请求

tqdm库

        下载百分比进度

IO方式下载临时文件

保存至指定路径并返回

import os
import shutil
import requests
import tempfile
from tqdm import tqdm
from typing import IO
from pathlib import Path
​
# 指定保存路径为 `home_path/.mindspore_examples`
cache_dir = Path.home() / '.mindspore_examples'
​
def http_get(url: str, temp_file: IO):"""使用requests库下载数据,并使用tqdm库进行流程可视化"""req = requests.get(url, stream=True)content_length = req.headers.get('Content-Length')total = int(content_length) if content_length is not None else Noneprogress = tqdm(unit='B', total=total)for chunk in req.iter_content(chunk_size=1024):if chunk:progress.update(len(chunk))temp_file.write(chunk)progress.close()
​
def download(file_name: str, url: str):"""下载数据并存为指定名称"""if not os.path.exists(cache_dir):os.makedirs(cache_dir)cache_path = os.path.join(cache_dir, file_name)cache_exist = os.path.exists(cache_path)if not cache_exist:with tempfile.NamedTemporaryFile() as temp_file:http_get(url, temp_file)temp_file.flush()temp_file.seek(0)with open(cache_path, 'wb') as cache_file:shutil.copyfileobj(temp_file, cache_file)return cache_path

下载IMDB数据集(使用华为云镜像):

imdb_path = download('aclImdb_v1.tar.gz', 'https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/aclImdb_v1.tar.gz')
imdb_path

输出:

100%|██████████| 84125825/84125825 [00:02<00:00, 38051349.02B/s]
'/home/nginx/.mindspore_examples/aclImdb_v1.tar.gz'

2.IMDB加载模块

Python的tarfile库

        读取IMDB数据集tar.gz文件

        所有数据和标签分别进行存放

IMDB数据集解压目录如下:

    ├── aclImdb│   ├── imdbEr.txt│   ├── imdb.vocab│   ├── README│   ├── test│   └── train│         ├── neg│         ├── pos...

数据集分两部分加载

        train

                neg

                pos

        Test

                neg

                pos

import re
import six
import string
import tarfile
​
class IMDBData():"""IMDB数据集加载器
​加载IMDB数据集并处理为一个Python迭代对象。
​"""label_map = {"pos": 1,"neg": 0}def __init__(self, path, mode="train"):self.mode = modeself.path = pathself.docs, self.labels = [], []
​self._load("pos")self._load("neg")
​def _load(self, label):pattern = re.compile(r"aclImdb/{}/{}/.*\.txt$".format(self.mode, label))# 将数据加载至内存with tarfile.open(self.path) as tarf:tf = tarf.next()while tf is not None:if bool(pattern.match(tf.name)):# 对文本进行分词、去除标点和特殊字符、小写处理self.docs.append(str(tarf.extractfile(tf).read().rstrip(six.b("\n\r")).translate(None, six.b(string.punctuation)).lower()).split())self.labels.append([self.label_map[label]])tf = tarf.next()
​def __getitem__(self, idx):return self.docs[idx], self.labels[idx]
​def __len__(self):return len(self.docs)

3.加载训练数据集

imdb_train = IMDBData(imdb_path, 'train')
len(imdb_train)

输出:

25000

mindspore.dataset.Generatordataset接口

加载数据集迭代对象

        加载训练数据集train

        加载测试数据集test

        指定数据集中文本和标签列名

import mindspore.dataset as ds
​
def load_imdb(imdb_path):imdb_train = ds.GeneratorDataset(IMDBData(imdb_path, "train"), column_names=["text", "label"], shuffle=True, num_samples=10000)imdb_test = ds.GeneratorDataset(IMDBData(imdb_path, "test"), column_names=["text", "label"], shuffle=False)return imdb_train, imdb_testimdb_train, imdb_test = load_imdb(imdb_path)
imdb_train

输出:

<mindspore.dataset.engine.datasets_user_defined.GeneratorDataset at 0xfffed0a44fd0>

4.加载预训练词向量

预训练词向量

Glove(Global Vectors for Word Representation)

        数值化表示输入单词

        构造Embedding层词向量和词表

                Glove

        nn.Embedding层

        查表方式

        输入

                单词对应词表中的index

        输出

                对应表达向量

预训练词向量

Word

Vector

the

0.418 0.24968 -0.41242 0.1217 0.34527 -0.044457 -0.49688 -0.17862 -0.00066023 ...

,

0.013441 0.23682 -0.16899 0.40951 0.63812 0.47709 -0.42852 -0.55641 -0.364 ...

第一列单词作词表

dataset.text.Vocab按序加载

读取每一行Vector

        转为numpy.array

nn.Embedding加载权重

import zipfile
import numpy as np
​
def load_glove(glove_path):glove_100d_path = os.path.join(cache_dir, 'glove.6B.100d.txt')if not os.path.exists(glove_100d_path):glove_zip = zipfile.ZipFile(glove_path)glove_zip.extractall(cache_dir)
​embeddings = []tokens = []with open(glove_100d_path, encoding='utf-8') as gf:for glove in gf:word, embedding = glove.split(maxsplit=1)tokens.append(word)embeddings.append(np.fromstring(embedding, dtype=np.float32, sep=' '))# 添加 <unk>, <pad> 两个特殊占位符对应的embeddingembeddings.append(np.random.rand(100))embeddings.append(np.zeros((100,), np.float32))
​vocab = ds.text.Vocab.from_list(tokens, special_tokens=["<unk>", "<pad>"], special_first=False)embeddings = np.array(embeddings).astype(np.float32)return vocab, embeddings

词表没有覆盖的单词加<unk>标记符

输入长度不一致

        打包batch时填充短文本加<pad>标记符

完成的词表长度为原词表长度+2。

下载Glove词向量

加载生成词表和词向量权重矩阵

glove_path = download('glove.6B.zip', 'https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/glove.6B.zip')
vocab, embeddings = load_glove(glove_path)
len(vocab.vocab())

输出:

100%|██████████| 862182613/862182613 [00:22<00:00, 38245398.49B/s]
400002

使用词表转换the为index id

查询词向量矩阵对应的词向量

idx = vocab.tokens_to_ids('the')
embedding = embeddings[idx]
idx, embedding

输出:

(0,array([-0.038194, -0.24487 ,  0.72812 , -0.39961 ,  0.083172,  0.043953,-0.39141 ,  0.3344  , -0.57545 ,  0.087459,  0.28787 , -0.06731 ,0.30906 , -0.26384 , -0.13231 , -0.20757 ,  0.33395 , -0.33848 ,-0.31743 , -0.48336 ,  0.1464  , -0.37304 ,  0.34577 ,  0.052041,0.44946 , -0.46971 ,  0.02628 , -0.54155 , -0.15518 , -0.14107 ,-0.039722,  0.28277 ,  0.14393 ,  0.23464 , -0.31021 ,  0.086173,0.20397 ,  0.52624 ,  0.17164 , -0.082378, -0.71787 , -0.41531 ,0.20335 , -0.12763 ,  0.41367 ,  0.55187 ,  0.57908 , -0.33477 ,-0.36559 , -0.54857 , -0.062892,  0.26584 ,  0.30205 ,  0.99775 ,-0.80481 , -3.0243  ,  0.01254 , -0.36942 ,  2.2167  ,  0.72201 ,-0.24978 ,  0.92136 ,  0.034514,  0.46745 ,  1.1079  , -0.19358 ,-0.074575,  0.23353 , -0.052062, -0.22044 ,  0.057162, -0.15806 ,-0.30798 , -0.41625 ,  0.37972 ,  0.15006 , -0.53212 , -0.2055  ,-1.2526  ,  0.071624,  0.70565 ,  0.49744 , -0.42063 ,  0.26148 ,-1.538   , -0.30223 , -0.073438, -0.28312 ,  0.37104 , -0.25217 ,0.016215, -0.017099, -0.38984 ,  0.87424 , -0.72569 , -0.51058 ,-0.52028 , -0.1459  ,  0.8278  ,  0.27062 ], dtype=float32))

四、数据集预处理

预处理

        mindspore.dataset接口

        Vocab处理

                text.Lookup接口

                加载词表

                指定unknown_token

                所有Token对应index id。

        文本序列统一长度

                PadEnd接口

                        定义最大长度 此例为500

                        补齐值(pad_value) 此例为<pad>

                不足的<pad>补齐

                超出的截断

        label数据转为float32格式。

import mindspore as ms
​
lookup_op = ds.text.Lookup(vocab, unknown_token='<unk>')
pad_op = ds.transforms.PadEnd([500], pad_value=vocab.tokens_to_ids('<pad>'))
type_cast_op = ds.transforms.TypeCast(ms.float32)

定义数据集处理流水线

添加指定column操作。

        map接口

imdb_train = imdb_train.map(operations=[lookup_op, pad_op], input_columns=['text'])
imdb_train = imdb_train.map(operations=[type_cast_op], input_columns=['label'])
​
imdb_test = imdb_test.map(operations=[lookup_op, pad_op], input_columns=['text'])
imdb_test = imdb_test.map(operations=[type_cast_op], input_columns=['label'])

分割两部分数据集

    split接口

            训练比例0.7

            验证比例0.3

imdb_train, imdb_valid = imdb_train.split([0.7, 0.3])

输出:

[WARNING] ME(281:281473514793264,MainProcess):2024-07-07-02:08:44.142.068 [mindspore/dataset/engine/datasets.py:1203] Dataset is shuffled before split.

打包数据集

        batch接口

                batch大小

                设置是否丢弃剩余数据(无法整除batch size的部分)

imdb_train = imdb_train.batch(64, drop_remainder=True)
imdb_valid = imdb_valid.batch(64, drop_remainder=True)

五、模型构建

情感分类模型结构

nn.Embedding -> nn.RNN -> nn.Dense

        输入文本(即序列化后的index id列表)

        查表转为向量化表示

        nn.Embedding层加载Glove词向量

        RNN循环神经网络做特征提取

                规避RNN梯度消失问题

                LSTM(Long short-term memory)变种

        RNN连接全连接层nn.Dense

        转化特征为与分类数量相同的size

1.Embedding

Embedding层EmbeddingLookup

        使用index id查找权重矩阵对应id的向量

        输入

                index id序列

        输出

                相同长度矩阵

        例如:

                # 词表大小(index的取值范围)为1000,表示向量的size为100

                embedding = nn.Embedding(1000, 100)

                # 序列长度为16

                input shape: (1, 16)                

                output shape: (1, 16, 100)

        预训练词向量矩阵glove

                nn.Embedding.embedding_table

        对应vocab_size 词表大小400002

        embedding_size  选用的glove.6B.100d向量大小100

2.RNN(循环神经网络)

RNN循环神经网络

Recurrent Neural Network

        输入序列sequence数据

        递归recursion序列演进

        所有节点(循环单元)按链式连接

RNN一般结构

左侧

        RNN Cell循环

                只有一个Cell参数

                在循环计算中更新

右侧

        RNN链式连接平铺

自然语言处理大量应用RNN

    匹配

        RNN的循环特性

        自然语言文本的序列特性

RNN结构拆解

RNN单个Cell结构简单

        梯度消失(Gradient Vanishing)问题

                序列较长时,序列尾部丢失首部信息

        提出LSTM(Long short-term memory)

                门控机制(Gating Mechanism)

                        控制信息流在每个循环步中的留存和丢弃

LSTM结构拆解

MindSpore.nn.LSTM对应公式:

h0:t,(ht,ct)=LSTM(x0:t,(h0,c0))

nn.LSTM隐藏了整个循环神经网络在序列时间步(Time step)上的循环

输入

        序列

        初始状态

输出

        时间步隐状态(hidden state)矩阵

        最后一个时间步隐状态

        输入下一层

                句子的编码特征

时间步Time step

        循环神经网络计算的每一次循环,成为一个Time step。

        输入

                文本序列时,一个Time step对应一个单词

        输出

                h0:t对应每个单词的隐状态集合

                ht,ct对应最后一个单词对应的隐状态

3.Dense

LSTM编码获取句子特征

输入全连接层nn.Dense

变换特征维度为二分类所需的维度1

输出模型预测结果

import math
import mindspore as ms
import mindspore.nn as nn
import mindspore.ops as ops
from mindspore.common.initializer import Uniform, HeUniform
​
class RNN(nn.Cell):def __init__(self, embeddings, hidden_dim, output_dim, n_layers,bidirectional, pad_idx):super().__init__()vocab_size, embedding_dim = embeddings.shapeself.embedding = nn.Embedding(vocab_size, embedding_dim, embedding_table=ms.Tensor(embeddings), padding_idx=pad_idx)self.rnn = nn.LSTM(embedding_dim,hidden_dim,num_layers=n_layers,bidirectional=bidirectional,batch_first=True)weight_init = HeUniform(math.sqrt(5))bias_init = Uniform(1 / math.sqrt(hidden_dim * 2))self.fc = nn.Dense(hidden_dim * 2, output_dim, weight_init=weight_init, bias_init=bias_init)
​def construct(self, inputs):embedded = self.embedding(inputs)_, (hidden, _) = self.rnn(embedded)hidden = ops.concat((hidden[-2, :, :], hidden[-1, :, :]), axis=1)output = self.fc(hidden)return output

4.损失函数与优化器

指定参数实例化网络

选择损失函数和优化器

预测Positive或Negative二分类问题

        nn.BCEWithLogitsLoss(二分类交叉熵损失函数)

hidden_size = 256
output_size = 1
num_layers = 2
bidirectional = True
lr = 0.001
pad_idx = vocab.tokens_to_ids('<pad>')
​
model = RNN(embeddings, hidden_size, output_size, num_layers, bidirectional, pad_idx)
loss_fn = nn.BCEWithLogitsLoss(reduction='mean')
optimizer = nn.Adam(model.trainable_params(), learning_rate=lr)

5.训练逻辑

训练逻辑设计

        读取一个Batch的数据;

        输入网络

                正向计算

                反向传播

                更新权重

        返回loss

tqdm库

        可视化

                训练过程

                loss

def forward_fn(data, label):logits = model(data)loss = loss_fn(logits, label)return loss
​
grad_fn = ms.value_and_grad(forward_fn, None, optimizer.parameters)
​
def train_step(data, label):loss, grads = grad_fn(data, label)optimizer(grads)return loss
​
def train_one_epoch(model, train_dataset, epoch=0):model.set_train()total = train_dataset.get_dataset_size()loss_total = 0step_total = 0with tqdm(total=total) as t:t.set_description('Epoch %i' % epoch)for i in train_dataset.create_tuple_iterator():loss = train_step(*i)loss_total += loss.asnumpy()step_total += 1t.set_postfix(loss=loss_total/step_total)t.update(1)

6.评估指标和逻辑

评估模型

        对比

                模型预测结果

                测试集正确标签

        求预测准确率

IMDB的情感二分类准确率实现代码

def binary_accuracy(preds, y):"""计算每个batch的准确率"""
​# 对预测值进行四舍五入rounded_preds = np.around(ops.sigmoid(preds).asnumpy())correct = (rounded_preds == y).astype(np.float32)acc = correct.sum() / len(correct)return acc

评估步骤

        读取一个Batch的数据;

        输入网络

                正向计算

                预测结果

        计算准确率

        tqdm可视化

                评估过程

                Loss

        输出评估loss

        判断模型优劣

评估时网络模型主体不包含损失函数和优化器

评估model.set_train(False)模型评估状态

def evaluate(model, test_dataset, criterion, epoch=0):total = test_dataset.get_dataset_size()epoch_loss = 0epoch_acc = 0step_total = 0model.set_train(False)
​with tqdm(total=total) as t:t.set_description('Epoch %i' % epoch)for i in test_dataset.create_tuple_iterator():predictions = model(i[0])loss = criterion(predictions, i[1])epoch_loss += loss.asnumpy()
​acc = binary_accuracy(predictions, i[1])epoch_acc += acc
​step_total += 1t.set_postfix(loss=epoch_loss/step_total, acc=epoch_acc/step_total)t.update(1)
​return epoch_loss / total

六、模型训练与保存

模型训练

        设置训练轮数5轮

        保存最优模型变量best_valid_loss

        保存最小loss值轮次模型

num_epochs = 2
best_valid_loss = float('inf')
ckpt_file_name = os.path.join(cache_dir, 'sentiment-analysis.ckpt')
​
for epoch in range(num_epochs):train_one_epoch(model, imdb_train, epoch)valid_loss = evaluate(model, imdb_valid, loss_fn, epoch)
​if valid_loss < best_valid_loss:best_valid_loss = valid_lossms.save_checkpoint(model, ckpt_file_name)

输出:

Epoch 0:   0%|          | 0/109 [00:00<?, ?it/s]
|
Epoch 0: 100%|██████████| 109/109 [13:38<00:00,  7.51s/it, loss=0.692]  
Epoch 0: 100%|██████████| 46/46 [00:40<00:00,  1.15it/s, acc=0.524, loss=0.69] 
Epoch 1: 100%|██████████| 109/109 [01:23<00:00,  1.31it/s, loss=0.668]
Epoch 1: 100%|██████████| 46/46 [00:13<00:00,  3.38it/s, acc=0.672, loss=0.615]

每轮Loss逐步下降

准确率逐步提升

七、模型加载与测试

模型测试

加载保存的最优模型

        加载checkpoint

        加载网络权重加载接口

param_dict = ms.load_checkpoint(ckpt_file_name)
ms.load_param_into_net(model, param_dict)

输出:

([], [])

测试集打batch

evaluate评估

得到模型在测试集上的效果

imdb_test = imdb_test.batch(64)
evaluate(model, imdb_test, loss_fn)

输出:

Epoch 0: 100%|█████████▉| 390/391 [01:29<00:00,  4.57it/s, acc=0.666, loss=0.619]
-
Epoch 0: 100%|██████████| 391/391 [03:33<00:00,  1.83it/s, acc=0.666, loss=0.619]
0.6193520278881883

八、自定义输入测试

预测函数

        输入一句评价

        获得评价的情感分类

现实步骤:

        输入句子分词;

        词表对应的index id序列;

        index id序列转为Tensor;

        输入模型

        获得预测结果;

        打印输出预测结果。

实现代码

score_map = {1: "Positive",0: "Negative"
}
​
def predict_sentiment(model, vocab, sentence):model.set_train(False)tokenized = sentence.lower().split()indexed = vocab.tokens_to_ids(tokenized)tensor = ms.Tensor(indexed, ms.int32)tensor = tensor.expand_dims(0)prediction = model(tensor)return score_map[int(np.round(ops.sigmoid(prediction).asnumpy()))]predict_sentiment(model, vocab, "This film is terrible")

输出:

'Negative'

predict_sentiment(model, vocab, "This film is great")

输出:

'Positive'

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

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

相关文章

放大镜案例

放大镜 <!DOCTYPE html> <html lang"zh-cn"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>商品放大镜</title><link rel&qu…

如何使用allure生成测试报告

第一步下载安装JDK1.8&#xff0c;参考链接JDK1.8下载、安装和环境配置教程-CSDN博客 第二步配置allure环境&#xff0c;参考链接allure的安装和使用(windows环境)_allure windows-CSDN博客 第三步&#xff1a; 第四步&#xff1a; pytest 查看目前运行的测试用例有无错误 …

如何使用 pytorch 创建一个神经网络

我已发布在&#xff1a;如何使用 pytorch 创建一个神经网络 SapientialM.Github.io 构建神经网络 1 导入所需包 import os import torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets, transforms2 检查GPU是否可用 dev…

Yolov10训练,转化onnx,推理

yolov10对于大目标的效果好&#xff0c;小目标不好 一、如果你训练过yolov5&#xff0c;yolov8&#xff0c;的话那么你可以直接用之前的环境就行 目录 一、如果你训练过yolov5&#xff0c;yolov8&#xff0c;的话那么你可以直接用之前的环境就行 二、配置好后就可以配置文件…

前端JS特效第24集:jquery css3实现瀑布流照片墙特效

jquery css3实现瀑布流照片墙特效&#xff0c;先来看看效果&#xff1a; 部分核心的代码如下(全部代码在文章末尾)&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8" /> <title>jquerycss3实现瀑…

Nginx:负载均衡小专题

运维专题 Nginx&#xff1a;负载均衡小专题 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/…

【专项刷题】— 位运算

常见类型介绍&#xff1a; & &#xff1a;有 0 就是 0 | &#xff1a;有 1 就是 1 ^ &#xff1a;相同为 0 &#xff0c;相异为 1 或者 无进位相加给定一个数确定它的二进制位的第x个数是0还是1&#xff1a;将一个数的二进制的第x位改成1&#xff1a;将一个数的二进制的第x…

Windows10/11家庭版开启Hyper-V虚拟机功能详解

Hyper-V是微软的一款虚拟机软件&#xff0c;可以使我们在一台Windows PC上&#xff0c;在虚拟环境下同时运行多个互相之间完全隔离的操作系统&#xff0c;这就实现了在Windows环境下运行Linux以及其他OS的可能性。和第三方虚拟机软件&#xff0c;如VMware等相比&#xff0c;Hyp…

大模型知识问答: 文本分块要点总结

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对大模型技术趋势、算法项目落地经验分享、新手如何入门算法岗、该如何准备面试攻略、面试常考点等热门话题进行了深入的讨论。 总结链接如…

C++ 信号量和锁的区别

网上关于信号量和锁的区别&#xff0c;写的比较官方晦涩难懂&#xff0c;对于这个知识点吸收难&#xff0c;通过示例&#xff0c;我们看到信号量&#xff0c;可以控制同一时刻的线程数量&#xff0c;就算同时开启很多线程&#xff0c;依然可以的达到线程数可控 #include <i…

初识c++(命名空间,缺省参数,函数重载)

一、命名空间 1、namespace的意义 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存在于全 局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化&#xff0c;以避免命名 冲突…

世界商用飞机机型大全-使用Java抓取FlightAware后的答案

目录 前言 一、数据说明 1、实时航班飞机机型数据 2、网页结构分析 二、使用Java进行信息抓取 1、定义页面PageVO对象 2、爬取属性定义 3、启动信息抓取组件 三、成果分析 1、商业飞行的飞机机型的种类 2、飞机种类排名前十名 3、航班数排名后十名 4、看中国国产大飞…

你真的会信息收集嘛,4k字渗透测试信息收集10大技巧

前言 在渗透测试中&#xff0c;信息收集是非常关键的一步&#xff0c;它为后续的漏洞发现和利用提供了重要的基础。以下是非常详细的信息收集方式&#xff1a; 一、被动信息收集 被动信息收集是指在不与目标系统直接交互的情况下&#xff0c;通过公开渠道获取目标系统的相关…

基于51单片机的四路抢答器Protues仿真设计

一、设计背景 近年来随着科技的飞速发展&#xff0c;单片机的应用正在不断的走向深入。本文阐述了基于51单片机的八路抢答器设计。本设计中&#xff0c;51单片机充当了核心控制器的角色&#xff0c;通过IO口与各个功能模块相连接。按键模块负责检测参与者的抢答动作&#xff0c…

力扣-贪心算法4

406.根据身高重建队列 406. 根据身高重建队列 题目 假设有打乱顺序的一群人站成一个队列&#xff0c;数组 people 表示队列中一些人的属性&#xff08;不一定按顺序&#xff09;。每个 people[i] [hi, ki] 表示第 i 个人的身高为 hi &#xff0c;前面 正好 有 ki 个身高大于或…

MyBatis的简介与使用

Mybatis JDBC操作数据库的缺点 存在大量的冗余代码。手工创建 Connection、Statement 等&#xff0c;效率低下。手工将结果集封装成实体对象。查询效率低&#xff0c;没有对数据访问进行优化。 Mybatis框架 简介 MyBatis 本是 apache 的一个开源项目 iBatis, 2010年这个项目由…

imx6ull/linux应用编程学习(14) MQTT基础知识

什么是mqtt&#xff1f; 与HTTP 协议一样&#xff0c; MQTT 协议也是应用层协议&#xff0c;工作在 TCP/IP 四层模型中的最上层&#xff08;应用层&#xff09;&#xff0c;构建于 TCP/IP协议上。 MQTT 最大优点在于&#xff0c;可以以极少的代码和有限的带宽&#xff0c;为连接…

网络资源模板--Android Studio 外卖点餐App

目录 一、项目演示 二、项目测试环境 三、项目详情 四、完整的项目源码 原创外卖点餐&#xff1a;基于Android studio 实现外卖(点)订餐系统 非原创奶茶点餐&#xff1a;网络资源模板--基于 Android Studio 实现的奶茶点餐App报告 一、项目演示 网络资源模板--基于Android …

在AvaotaA1全志T527开发板上使用AvaotaOS 部署 Docker 服务

Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Linux或Windows操作系统的机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间不会有任何接口。 准备…

信息技术课上的纪律秘诀:营造有序学习环境

信息技术课是学生们探索数字世界的乐园&#xff0c;但同时也是课堂纪律管理的挑战场。电脑、网络、游戏等元素可能分散学生的注意力&#xff0c;影响学习效果。本文将分享一些有效的策略&#xff0c;帮助教师在信息技术课上维持课堂纪律&#xff0c;确保教学活动顺利进行。 制…