使用pytorch搭建textCNN、BERT、transformer进行文本分类

首先展示数据处理后的类型:
在这里插入图片描述
第一列为文本,第二类为标注的标签,数据保存在xlsx的表格中,分为训练集和验证集。

textCNN

直接上整个工程代码:

import pandas as pd
import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from transformers import BertTokenizer, BertModel
import random
from sklearn.metrics import classification_report# 设置随机种子以确保结果可复现
def set_seed(seed):random.seed(seed)np.random.seed(seed)torch.manual_seed(seed)if torch.cuda.is_available():torch.cuda.manual_seed(seed)torch.cuda.manual_seed_all(seed)set_seed(42)# 使用预训练的 BERT 模型和分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
bert_model = BertModel.from_pretrained('bert-base-chinese')# 定义一个函数来处理文本数据
def preprocess(text):encoding = tokenizer.encode_plus(text,add_special_tokens=True,max_length=150,padding='max_length',return_attention_mask=True,return_tensors='pt',truncation=True)return encoding['input_ids'].squeeze(), encoding['attention_mask'].squeeze()# 读取训练和验证数据
train_df = pd.read_excel('../train.xlsx')
val_df = pd.read_excel('../val.xlsx')# 处理训练数据
train_texts = train_df['comment'].apply(preprocess)
train_labels = torch.tensor(train_df['label'].values)
train_input_ids = torch.stack([x[0] for x in train_texts])
train_attention_masks = torch.stack([x[1] for x in train_texts])# 处理验证数据
val_texts = val_df['comment'].apply(preprocess)
val_labels = torch.tensor(val_df['label'].values)
val_input_ids = torch.stack([x[0] for x in val_texts])
val_attention_masks = torch.stack([x[1] for x in val_texts])# 创建数据集和数据加载器
class TextDataset(Dataset):def __init__(self, input_ids, attention_masks, labels):self.input_ids = input_idsself.attention_masks = attention_masksself.labels = labelsdef __len__(self):return len(self.labels)def __getitem__(self, idx):return {'input_ids': self.input_ids[idx],'attention_mask': self.attention_masks[idx],'labels': self.labels[idx]}train_dataset = TextDataset(train_input_ids, train_attention_masks, train_labels)
val_dataset = TextDataset(val_input_ids, val_attention_masks, val_labels)train_dataloader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_dataloader = DataLoader(val_dataset, batch_size=32, shuffle=False)# 检查是否有可用的 GPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f'Using device: {device}')# 定义模型
class TextCNN(nn.Module):def __init__(self, bert_model, num_classes):super(TextCNN, self).__init__()self.bert_model = bert_modelself.conv1 = nn.Conv2d(1, 100, (3, 768))self.conv2 = nn.Conv2d(1, 100, (4, 768))self.conv3 = nn.Conv2d(1, 100, (5, 768))self.dropout = nn.Dropout(0.5)self.fc = nn.Linear(300, num_classes)def forward(self, input_ids, attention_mask):with torch.no_grad():embedded = self.bert_model(input_ids, attention_mask).last_hidden_stateembedded = embedded.unsqueeze(1)conv1 = F.relu(self.conv1(embedded)).squeeze(3)conv2 = F.relu(self.conv2(embedded)).squeeze(3)conv3 = F.relu(self.conv3(embedded)).squeeze(3)pooled1 = F.max_pool1d(conv1, conv1.size(2)).squeeze(2)pooled2 = F.max_pool1d(conv2, conv2.size(2)).squeeze(2)pooled3 = F.max_pool1d(conv3, conv3.size(2)).squeeze(2)out = torch.cat((pooled1, pooled2, pooled3), 1)out = self.dropout(out)return self.fc(out)# 初始化模型、损失函数和优化器
model = TextCNN(bert_model, num_classes=2).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 训练和验证模型,并保存最好的模型和最后一轮的模型
def train_and_evaluate(model, train_dataloader, val_dataloader, criterion, optimizer, device, epochs=10):best_val_accuracy = 0.0best_model_path = "best_model.pth"last_model_path = "last_model.pth"for epoch in range(epochs):model.train()train_loss = 0for batch in train_dataloader:input_ids = batch['input_ids'].to(device)attention_mask = batch['attention_mask'].to(device)labels = batch['labels'].to(device)optimizer.zero_grad()outputs = model(input_ids, attention_mask)loss = criterion(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item()train_loss /= len(train_dataloader)print(f"Epoch {epoch + 1}, Training Loss: {train_loss}")model.eval()val_loss = 0correct = 0total = 0all_preds = []all_labels = []with torch.no_grad():for batch in val_dataloader:input_ids = batch['input_ids'].to(device)attention_mask = batch['attention_mask'].to(device)labels = batch['labels'].to(device)outputs = model(input_ids, attention_mask)loss = criterion(outputs, labels)val_loss += loss.item()_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()all_preds.extend(predicted.cpu().numpy())all_labels.extend(labels.cpu().numpy())val_loss /= len(val_dataloader)accuracy = 100 * correct / totalprint(f"Validation Loss: {val_loss}, Validation Accuracy: {accuracy}%")# 打印分类报告print("Classification Report:")print(classification_report(all_labels, all_preds, digits=3))# 保存验证集上表现最好的模型if accuracy > best_val_accuracy:best_val_accuracy = accuracytorch.save(model.state_dict(), best_model_path)print(f"Best model saved with accuracy: {best_val_accuracy}%")# 保存最后一轮的模型torch.save(model.state_dict(), last_model_path)print(f"Last model saved.")train_and_evaluate(model, train_dataloader, val_dataloader, criterion, optimizer, device)

可以根据自己爬取的文本的长度来自定义preprocess()函数里面的max_length值,若文本长度超过定义的最大值将进行截断,若不足则padding。最好包括大部分文本的长度,模型效果会比较好。

运行起来可能会报以下错误:

OSError: Can't load tokenizer for 'bert-base-chinese'. If you were trying to load it from 'https://huggingface.co/models', make sure you don't have a local directory with the same name. Otherwise, make sure 'bert-base-chinese' is the correct path to a directory containing all relevant files for a BertTokenizer tokenizer.

说明自动下载可能出现问题我们可以手动下载。
访问给出的网站https://huggingface.co/models,然后搜索bert-base-chinese,如图选择第一个。
在这里插入图片描述
点进去后下载config.json、pytorch_model.bin 和 vocab.txt三个文件,在工程的同一路径下创建“bert-base-chinese”的文件夹,将三个文件放入其中。
在这里插入图片描述
将使用预训练的 BERT 模型和分词器的两行代码该文调用本地:

tokenizer = BertTokenizer.from_pretrained('./bert-base-chinese')
bert_model = BertModel.from_pretrained('./bert-base-chinese')

运行结果:
在这里插入图片描述

BERT

跟textCNN一样用相同的BERT 模型和分词器:

import pandas as pd
import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader
import torch.nn as nn
import torch.optim as optim
from transformers import BertTokenizer, BertModel, BertConfig
import random
from sklearn.metrics import classification_report# 设置随机种子以确保结果可复现
def set_seed(seed):random.seed(seed)np.random.seed(seed)torch.manual_seed(seed)if torch.cuda.is_available():torch.cuda.manual_seed(seed)torch.cuda.manual_seed_all(seed)set_seed(42)# 使用预训练的 BERT 模型和分词器
tokenizer = BertTokenizer.from_pretrained('./bert-base-chinese')
bert_model = BertModel.from_pretrained('./bert-base-chinese')# 定义一个函数来处理文本数据
def preprocess(text):encoding = tokenizer.encode_plus(text,add_special_tokens=True,max_length=150,padding='max_length',return_attention_mask=True,return_tensors='pt',truncation=True)return encoding['input_ids'].squeeze(), encoding['attention_mask'].squeeze()# 读取训练和验证数据
train_df = pd.read_excel('../train.xlsx')
val_df = pd.read_excel('../val.xlsx')# 处理训练数据
train_texts = train_df['comment'].apply(preprocess)
train_labels = torch.tensor(train_df['label'].values)
train_input_ids = torch.stack([x[0] for x in train_texts])
train_attention_masks = torch.stack([x[1] for x in train_texts])# 处理验证数据
val_texts = val_df['comment'].apply(preprocess)
val_labels = torch.tensor(val_df['label'].values)
val_input_ids = torch.stack([x[0] for x in val_texts])
val_attention_masks = torch.stack([x[1] for x in val_texts])# 创建数据集和数据加载器
class TextDataset(Dataset):def __init__(self, input_ids, attention_masks, labels):self.input_ids = input_idsself.attention_masks = attention_masksself.labels = labelsdef __len__(self):return len(self.labels)def __getitem__(self, idx):return {'input_ids': self.input_ids[idx],'attention_mask': self.attention_masks[idx],'labels': self.labels[idx]}train_dataset = TextDataset(train_input_ids, train_attention_masks, train_labels)
val_dataset = TextDataset(val_input_ids, val_attention_masks, val_labels)train_dataloader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_dataloader = DataLoader(val_dataset, batch_size=32, shuffle=False)# 检查是否有可用的 GPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f'Using device: {device}')# 定义模型
class BertForTextClassification(nn.Module):def __init__(self, bert_model, num_classes):super(BertForTextClassification, self).__init__()self.bert = bert_modelself.dropout = nn.Dropout(0.5)self.classifier = nn.Linear(bert_model.config.hidden_size, num_classes)def forward(self, input_ids, attention_mask):outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask)pooled_output = outputs.pooler_outputpooled_output = self.dropout(pooled_output)logits = self.classifier(pooled_output)return logits# 初始化模型、损失函数和优化器
model = BertForTextClassification(bert_model, num_classes=2).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.00001)# 训练和验证模型,并保存最好的模型和最后一轮的模型
def train_and_evaluate(model, train_dataloader, val_dataloader, criterion, optimizer, device, epochs=10):best_val_accuracy = 0.0best_model_path = "best_model.pth"last_model_path = "last_model.pth"for epoch in range(epochs):model.train()train_loss = 0for batch in train_dataloader:input_ids = batch['input_ids'].to(device)attention_mask = batch['attention_mask'].to(device)labels = batch['labels'].to(device)optimizer.zero_grad()outputs = model(input_ids, attention_mask)loss = criterion(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item()train_loss /= len(train_dataloader)print(f"Epoch {epoch + 1}, Training Loss: {train_loss}")model.eval()val_loss = 0correct = 0total = 0all_preds = []all_labels = []with torch.no_grad():for batch in val_dataloader:input_ids = batch['input_ids'].to(device)attention_mask = batch['attention_mask'].to(device)labels = batch['labels'].to(device)outputs = model(input_ids, attention_mask)loss = criterion(outputs, labels)val_loss += loss.item()_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()all_preds.extend(predicted.cpu().numpy())all_labels.extend(labels.cpu().numpy())val_loss /= len(val_dataloader)accuracy = 100 * correct / totalprint(f"Validation Loss: {val_loss}, Validation Accuracy: {accuracy}%")# 打印分类报告print("Classification Report:")print(classification_report(all_labels, all_preds, digits=3))# 保存验证集上表现最好的模型if accuracy > best_val_accuracy:best_val_accuracy = accuracytorch.save(model.state_dict(), best_model_path)print(f"Best model saved with accuracy: {best_val_accuracy}%")# 保存最后一轮的模型torch.save(model.state_dict(), last_model_path)print(f"Last model saved.")train_and_evaluate(model, train_dataloader, val_dataloader, criterion, optimizer, device)

运行结果:
在这里插入图片描述

transformer

transformer使用的是自己的预训练模型和分词器,如果需要提前手动下载的话访问Hugging Face的官网还是下载config.json、pytorch_model.bin 和 vocab.txt三个文件,保存在hfl/chinese-roberta-wwm-ext目录中。

import pandas as pd
import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader
import torch.nn as nn
import torch.optim as optim
from transformers import AutoTokenizer, AutoModel
import random
from sklearn.metrics import classification_report# 设置随机种子以确保结果可复现
def set_seed(seed):random.seed(seed)np.random.seed(seed)torch.manual_seed(seed)if torch.cuda.is_available():torch.cuda.manual_seed(seed)torch.cuda.manual_seed_all(seed)set_seed(42)# 使用预训练的 Transformer 模型和分词器
model_name = './hfl/chinese-roberta-wwm-ext'
tokenizer = AutoTokenizer.from_pretrained(model_name)
transformer_model = AutoModel.from_pretrained(model_name)# 定义一个函数来处理文本数据
def preprocess(text):encoding = tokenizer.encode_plus(text,add_special_tokens=True,max_length=150,padding='max_length',return_attention_mask=True,return_tensors='pt',truncation=True)return encoding['input_ids'].squeeze(), encoding['attention_mask'].squeeze()# 读取训练和验证数据
train_df = pd.read_excel('../train.xlsx')
val_df = pd.read_excel('../val.xlsx')# 处理训练数据
train_texts = train_df['comment'].apply(preprocess)
train_labels = torch.tensor(train_df['label'].values)
train_input_ids = torch.stack([x[0] for x in train_texts])
train_attention_masks = torch.stack([x[1] for x in train_texts])# 处理验证数据
val_texts = val_df['comment'].apply(preprocess)
val_labels = torch.tensor(val_df['label'].values)
val_input_ids = torch.stack([x[0] for x in val_texts])
val_attention_masks = torch.stack([x[1] for x in val_texts])# 创建数据集和数据加载器
class TextDataset(Dataset):def __init__(self, input_ids, attention_masks, labels):self.input_ids = input_idsself.attention_masks = attention_masksself.labels = labelsdef __len__(self):return len(self.labels)def __getitem__(self, idx):return {'input_ids': self.input_ids[idx],'attention_mask': self.attention_masks[idx],'labels': self.labels[idx]}train_dataset = TextDataset(train_input_ids, train_attention_masks, train_labels)
val_dataset = TextDataset(val_input_ids, val_attention_masks, val_labels)train_dataloader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_dataloader = DataLoader(val_dataset, batch_size=32, shuffle=False)# 检查是否有可用的 GPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f'Using device: {device}')# 定义模型
class TransformerForTextClassification(nn.Module):def __init__(self, transformer_model, num_classes):super(TransformerForTextClassification, self).__init__()self.transformer = transformer_modelself.dropout = nn.Dropout(0.5)self.classifier = nn.Linear(transformer_model.config.hidden_size, num_classes)def forward(self, input_ids, attention_mask):outputs = self.transformer(input_ids=input_ids, attention_mask=attention_mask)pooled_output = outputs.pooler_output if 'pooler_output' in outputs else outputs.last_hidden_state[:, 0]pooled_output = self.dropout(pooled_output)logits = self.classifier(pooled_output)return logits# 初始化模型、损失函数和优化器
model = TransformerForTextClassification(transformer_model, num_classes=2).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.00001)# 训练和验证模型,并保存最好的模型和最后一轮的模型
def train_and_evaluate(model, train_dataloader, val_dataloader, criterion, optimizer, device, epochs=10):best_val_accuracy = 0.0best_model_path = "best_model.pth"last_model_path = "last_model.pth"for epoch in range(epochs):model.train()train_loss = 0for batch in train_dataloader:input_ids = batch['input_ids'].to(device)attention_mask = batch['attention_mask'].to(device)labels = batch['labels'].to(device)optimizer.zero_grad()outputs = model(input_ids, attention_mask)loss = criterion(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item()train_loss /= len(train_dataloader)print(f"Epoch {epoch + 1}, Training Loss: {train_loss}")model.eval()val_loss = 0correct = 0total = 0all_preds = []all_labels = []with torch.no_grad():for batch in val_dataloader:input_ids = batch['input_ids'].to(device)attention_mask = batch['attention_mask'].to(device)labels = batch['labels'].to(device)outputs = model(input_ids, attention_mask)loss = criterion(outputs, labels)val_loss += loss.item()_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()all_preds.extend(predicted.cpu().numpy())all_labels.extend(labels.cpu().numpy())val_loss /= len(val_dataloader)accuracy = 100 * correct / totalprint(f"Validation Loss: {val_loss}, Validation Accuracy: {accuracy}%")# 打印分类报告print("Classification Report:")print(classification_report(all_labels, all_preds, digits=3))# 保存验证集上表现最好的模型if accuracy > best_val_accuracy:best_val_accuracy = accuracytorch.save(model.state_dict(), best_model_path)print(f"Best model saved with accuracy: {best_val_accuracy}%")# 保存最后一轮的模型torch.save(model.state_dict(), last_model_path)print(f"Last model saved.")train_and_evaluate(model, train_dataloader, val_dataloader, criterion, optimizer, device)

运行结果:
在这里插入图片描述

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

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

相关文章

springMVC返回对象或List集合时报错 无法解析

报错信息 :No converter found for return value of type: class java.util.ArrayList 原因:没有导入json 所以java在返回对象时解析错误 解决:1、添加所需的依赖:确保在项目的依赖管理中添加了适当的 JSON 库,如 J…

c++函数基础总结

在给出的代码片段中,我们看到两部分内容:一个类定义和一个全局函数声明。让我们逐一分析它们: 类定义: cpp复制代码 class { public: void a(); }; 这个类定义是不完整的,因为它没有类名。但为了说明,我…

Linux开发工具(个人使用)

Linux开发工具 1.Linux yum软件包管理器1.1Linux安装程序有三种方式1.2注意事项1.3如何查看,安装,卸载软件包1.3.1查看软件包1.3.2安装软件包1.3.3卸载软件 2.Linux vim编辑器2.1vim的基本操作2.2vim正常模式命令集2.3vim底行模式命令集2.4vim配置 3.Lin…

金色晚年的温暖旋律

​在小镇的东头,有一座带着些许岁月痕迹的二层小楼。这里住着一位刚刚退休的老人,李大爷。他的退休生活并不像人们想象的那样枯燥无味,反而充满了色彩和活力。 退休后的李大爷并没有选择整日坐在摇椅上晒太阳,而是找到了新的生活…

如何设置eclipse中web.xml 文件的地址

新学了一个项目 ,项目结构与平常自己构建的web项目不同 ,用eclipse打开之后,eclipse竟然自己创建了一个web.xml 而项目里面原本的web.xml 文件eclipse没有识别出来,导致后来浏览器访问任何路径都报错404 一、修改项目中web.xml的…

Centos7.9环境下安装Keepalived(亲测版)

目录 一、在线安装 二、离线安装 (1)、 下载 (2)、安装依赖包 (3)、解压文件 (4)、编译 (4.1)、进入 keepalived-2.2.8 目录中 (4.2)、安装Keepalived (5)、配置文件修改 (6)、启动 (7)、检查启动状态 (8)、 设置开机自启 (9)、配置从节点 (10)、启动从节点keepalived…

vue3中实现鼠标点击后出现点击特效

一、效果展示 图片下方为效果体验地址 缓若江海凝清光 二、代码 js中&#xff1a; <script setup lang"ts"> window.addEventListener("click", (e: MouseEvent) > {const pointer document.createElement("div");pointer.classLi…

Oracle索引的在线添加方法

在Oracle中&#xff0c;索引的在线添加方法主要是通过使用CREATE INDEX语句时添加ONLINE选项来实现的。以下是关于Oracle索引在线添加方法的详细步骤和要点&#xff1a; 了解在线添加索引的概念&#xff1a; 在线添加索引意味着在创建索引的过程中&#xff0c;其他数据库操作…

头歌数据结构与算法课程设计中-硬币找零

给定n种不同面值的硬币k_i和每种硬币的数量x_i以及一个总金额k,请编写一个程序计算最少需要几枚硬币凑出这个金额k,凑出的方案是什么? 如果凑不出则输出“凑不出” 输入描述: 第一行两个正整数,n和k 然后n行每行两个数k_i和x_i 表示k_i面值的硬币有x_i个,中间以空格分隔 输…

k8s处于pending状态的原因有哪些

k8s处于pending状态的原因 资源不足&#xff1a;集群中的资源&#xff08;如CPU、内存&#xff09;不足以满足Pod所需的资源请求&#xff0c;导致Pod无法调度。 调度器问题&#xff1a;调度器无法为Pod找到合适的节点进行调度&#xff0c;可能是由于节点资源不足或调度策略配置…

数模混合芯片之可靠性设计

一、可靠性设计目的 数模混合芯片设计之所以需要可靠性设计&#xff0c;主要原因有以下几点&#xff1a; 工艺与环境影响&#xff1a; 半导体制造工艺存在着不可避免的随机和系统性偏差&#xff0c;这可能导致芯片内部的模拟电路和数字电路参数发生变化&#xff0c;影响性能…

CobaltStrike基本渗透

目录 CobaltStrike简介 主要功能&#xff1a; 使用注意&#xff1a; 在使用CobaltStrike进行渗透测试时&#xff0c;务必遵守法律法规&#xff0c;并获得合法授权。 CobaltStrike安装 前提 安装 服务端安装 windows安装 CS基本使用 监听器配置 一些基本的攻击…

算法(十四)动态规划

算法概念 动态规划&#xff08;Dynamic Programming&#xff09;是一种分阶段求解的算法思想&#xff0c;通过拆分问题&#xff0c;定义问题状态和状态之间的关系&#xff0c;使得问题能够以递推&#xff08;分治&#xff09;的方式去解决。动态规划中有三个重点概念&#xff…

【监控】prometheus自定义指标 exporter

一、【写在前面】 prometheus自定义指标本质是用代码自己写一个网络访问的采集器&#xff0c;你可以在官网看到&#xff0c;Client libraries | Prometheus官方支持的语言有GO JAVA PYTHON RUBY RUST, 第三方的库就支持的更多了&#xff0c;有BASH C CPP LUA C# JS PHP R PER…

智慧医院物联网建设-统一管理物联网终端及应用

近年来&#xff0c;国家卫健委相继出台的政策和评估标准体系中&#xff0c;都涵盖了强化物联网建设的内容。物联网建设已成为智慧医院建设的核心议题之一。 作为医院高质量发展的关键驱动力&#xff0c;物联网的顶层设计与网络架构设计规划&#xff0c;既需要结合现代信息技术的…

Keras深度学习框架基础第四讲:层接口(layers API)“层权重约束”

1、层权重约束概述 1.1 层权重约束的定义 Keras层权重约束的定义主要涉及到在训练神经网络模型时&#xff0c;对层的权重参数施加一定的限制或约束&#xff0c;以提高模型的泛化能力和稳定性。以下是关于Keras层权重约束的详细定义&#xff1a; 约束的目的&#xff1a; 防止…

APM编程环境:深度探索与未来展望

APM编程环境&#xff1a;深度探索与未来展望 APM编程环境&#xff0c;一个充满神秘与挑战的领域&#xff0c;吸引了无数开发者与研究者的目光。这个环境不仅提供了强大的编程工具与平台&#xff0c;更在编程逻辑、代码优化等方面展现了前所未有的可能性。接下来&#xff0c;我…

「前端+鸿蒙」核心技术HTML5+CSS3(六)

1、CSS默认宽度详解 在CSS中,默认情况下,块级元素(如<div>、<p>等)的宽度是auto,这意味着它们会根据内容自动调整宽度。内联元素(如<span>、<a>等)的宽度同样会根据其内部内容的宽度来决定。 为了控制元素的宽度,可以使用width属性来手动设置…

Python3位运算符

前言 本文介绍的是位运算符&#xff0c;位运算可以理解成对二进制数字上的每一个位进行操作的运算&#xff0c;位运算分为 布尔位运算符 和 移位位运算符。 文章目录 前言一、位运算概览1、布尔位运算符1&#xff09;按位与运算符 ( & )2&#xff09;按位或运算符 ( | )3…

一款C#开源、简单、免费的屏幕录制和GIF动画制作神器

前言 今天要给大家推荐一款由C#语言开发且开源的操作简单、免费的屏幕录制和GIF动画制作神器&#xff1a;ScreenToGif 。 工具介绍 ScreenToGif 是一款免费的开源屏幕录制和GIF 制作工具。它可以帮助用户捕捉计算机屏幕上的实时动画&#xff0c;并将其保存为高质量的 GIF 图像…