Pytorch框架—文本情感分类问题项目(二)

整体过程就是首先拿到了数据集微博100K,对个这个评论数据集进行处理,分类标签和评论内容。对评论内容进行分词处理,之后进行词频统计对高词频的进行编码,低词频的进用《UNK》表示,并使用《PAD》把他们扩展到等长列表便于处理。

拿到处理好的数据集,将其输入通过嵌入层得到密集表示向量表示,之后通过LSTM层,激活函数层,池化层,全连接层,最后应用softmax激活函数,得到类别概率。

1 数据准备

训练集 微博评论100K

停用词 采用合工大停用词表

对数据进行处理->拿到字典->利用字典对语料信息进行编码

1 读取评论和停用词文件

2 对评论内容进行分词处理并进行停用词过滤操作

3 根据分词结果统计词典

4 对词典进行排序 取top n的词作为最终词典,其余词作为同一个字符(因为不重要,提高运算速度)(UNK,PAD放最后)

data_processing.py

# coding=utf-8import jieba  # jieba中文分词使用# 微博评论数据路径
data_path = "sources/weibo_senti_100k.csv"
# 停用词路径
data_stop_path = "sources/hit_stopword.txt"
# 读取文件中的每一行,并将每一行作为一个字符串存储在一个列表中,跳过第一行
data_list = open(data_path, encoding="utf-8").readlines()[1:]
# 拿到停用词列表
stops_word = open(data_stop_path, encoding="utf-8").readlines()
# 过滤停用词换行符
stops_word = [line.strip() for line in stops_word]
# 手动添加过滤空格和换行
stops_word.append(" ")
stops_word.append("\n")# 定义统计字典
voc_dict = {}
# 字典中的最小词频数
min_seq = 1
# 取字典中前top_n个
top_n = 1000
# 对于前1000以为的值为UNK
UNK = "<UNK>"
# NLP建模需要PAD到固定长度
PAD = "<PAD>"# 对每条评论进行分词处理
for item in data_list:# 标签 1代表积极 0代表消极label = item[0]# 评论内容content = item[2:].strip()  # .strip() 方法去除前后的空格。# 使用jieba进行分词  例:梦想 有 多 大 , 舞台 就 有 多 大 ! 鼓掌seg_list = jieba.cut(content, cut_all=False)# 去除停用词后的最终分词结果seg_res = []# 去除停用词并创建词频字典for seg_item in seg_list:# 判断分词词语是否为停用词if (seg_item in stops_word):continueseg_res.append(seg_item)# seg_res : ['梦想', '大', '舞台', '大', '!', '鼓掌']# 判断该词语是否在字典中if seg_item in voc_dict.keys():voc_dict[seg_item] = voc_dict[seg_item] + 1  # 在的话词频+1else:voc_dict[seg_item] = 1  # 不在就加进字典去# voc_dict:{'\ufeff': 1, '更博': 1, '爆照': 2, '帅': 3, '越来越': 1, '爱': 4, '生快': 1, '傻': 1, '缺': 1}# 对字典进行排序
voc_list = sorted([_ for _ in voc_dict.items() if _[1] > min_seq],key=lambda x: x[1],  # key=lambda x:x[1]:指定排序的依据是每个项中的第二个元素(即值)。reverse=True)[:top_n]
"""
for idx, word_count in enumerate(voc_list):print(idx," ",word_count)0   ('爱', 6)
1   ('都', 2)
2   ('大', 2)
"""# 将处理后的字典重新赋值给voc_dict
voc_dict = {word_count[0]: idx for idx, word_count in enumerate(voc_list)}  # enumerate得到voc_list的键值和索引值# UNK:len(voc_dict) 表示将 UNK 这个词映射到一个特定的索引值 len(voc_dict)。这意味着,如果在后续的处理中遇到 UNK,它将被视为一个有效的词汇,并被分配一个特定的索引。
# PAD:len(voc_dict)+1 类似地,将 PAD 映射到一个比 voc_dict 中最后一个词汇的索引大 1 的值。这通常用于填充序列,使其达到固定的长度。
voc_dict.update({UNK: len(voc_dict), PAD: len(voc_dict) + 1})# 保存字典
ff = open("sources/dict", "w", encoding="utf-8")
for item in voc_dict.keys():ff.writelines("{},{}\n".format(item, voc_dict[item]))
ff.close()

dataset类的定义 自定义训练模型的数据类

作用 利用字典对词进行编码操作 拿到编码后的数据集

1 实现text_CLS(Dataset):类,包括初始化,获取长度,获得编码后的分词数据集

2 实现初始化

   通过load_data对数据集进行分词,过滤停用词,拿到数据集的数据字典和最大分词长度

3 实现获取长度

 获得数据集长度

4 实现获得编码后的分词数据集

编码是自己之保存了词频超过1的,词频为1的用UNK表示,为了统一长度用PAD的编码填充。

datasets.py

from torch.utils.data import Dataset, DataLoader  # 从 torch 库中导入数据集(Dataset)和数据加载器(DataLoader)类
import jieba  # 导入中文分词库 jieba
import numpy as np  # 导入科学计算库 numpy# 在 PyTorch 中,Dataset 是一个抽象类,用于表示数据集。它提供了一种统一的接口,用于读取和处理数据,
# 并与 DataLoader 结合使用,实现数据的批处理和迭代加载。# 读取字典
def read_dict(voc_dict_path):voc_dict = {}# 读取字典中的内容 {泪,0 嘻嘻,1 都,2 爱,3...}dict_list = open(voc_dict_path, encoding="utf-8").readlines()for item in dict_list:item = item.split(",")voc_dict[item[0]] = int(item[1].strip())# 拿到字典return voc_dict#加载数据
#获得 [['1', ['\ufeff', '更博', '爆照', '帅', '越来越', '爱', '生快', '傻', '缺', '爱', '爱', '爱']], ['1', ['张晓鹏', 'jonathan', '土耳其', '事要', '认真对待', '直接', '开除', '丁丁', '看', '世界', '很', '细心', '酒店', '都', '全部', 'OK']]]
#和 最大的字典项长度
def load_data(data_path, data_stop_path):# 读取文件中的每一行,并将每一行作为一个字符串存储在一个列表中,跳过第一行data_list = open(data_path, encoding="utf-8").readlines()[1:]# 拿到停用词列表stops_word = open(data_stop_path, encoding="utf-8").readlines()# 过滤停用词换行符stops_word = [line.strip() for line in stops_word]# 手动添加过滤空格和换行stops_word.append(" ")stops_word.append("\n")# 定义统计字典voc_dict = {}# 定义存储最终数据data = []# 最长句子的长度max_len_seq = 0# 对每条评论进行分词处理for item in data_list:# 标签 1代表积极 0代表消极label = item[0]# 评论内容content = item[2:].strip()  # .strip() 方法去除前后的空格。# 使用jieba进行分词  例:梦想 有 多 大 , 舞台 就 有 多 大 ! 鼓掌seg_list = jieba.cut(content, cut_all=False)# 去除停用词后的最终分词结果seg_res = []# 去除停用词并创建词频字典for seg_item in seg_list:# 判断分词词语是否为停用词if (seg_item in stops_word):continueseg_res.append(seg_item)# seg_res : ['梦想', '大', '舞台', '大', '!', '鼓掌']# 判断该词语是否在字典中if seg_item in voc_dict.keys():voc_dict[seg_item] = voc_dict[seg_item] + 1  # 在的话词频+1else:voc_dict[seg_item] = 1  # 不在就加进字典去# voc_dict:{'\ufeff': 1, '更博': 1, '爆照': 2, '帅': 3, '越来越': 1, '爱': 4, '生快': 1, '傻': 1, '缺': 1}# 记录最长句子的长度  #将句子PAD到固定的长度 以最长的句子为基准if len(seg_res) > max_len_seq:max_len_seq = len(seg_res)# 添加到数据集data  [['1', ['\ufeff', '更博', '爆照', '帅', '越来越', '爱', '生快', '傻', '缺', '爱', '爱', '爱']], ['1', ['张晓鹏', 'jonathan', '土耳其', '事要', '认真对待', '直接', '开除', '丁丁', '看', '世界', '很', '细心', '酒店', '都', '全部', 'OK']]]data.append([label, seg_res])# print(data)return data, max_len_seqclass text_CLS(Dataset):def __init__(self, voc_dict_path, data_path, data_stop_path):# 微博评论数据路径self.data_path = data_path# 停用词路径self.data_stop_path = data_stop_path# 拿到字典self.voc_dict = read_dict(voc_dict_path)# 加载训练数据self.data, self.max_len_path = load_data(self.data_path, self.data_stop_path)# 随机打乱一个数组。np.random.shuffle(self.data)def __len__(self):return len(self.data)def __getitem__(self, item):data = self.data[item]  # ['1', ['\ufeff', '更博', '爆照', '帅', '越来越', '爱', '生快', '傻', '缺', '爱', '爱', '爱']]lable = int(data[0])  # 1word_list = data[1]  # ['\ufeff', '更博', '爆照', '帅', '越来越', '爱', '生快', '傻', '缺', '爱', '爱', '爱']input_idx = []# 将word转化为对应的idfor word in word_list:if word in self.voc_dict.keys():  # 在字典中取字典的编码input_idx.append(self.voc_dict[word])else:  # 不在取UNKinput_idx.append(self.voc_dict["<UNK>"])# 对齐长度 以最大的为基准if len(input_idx) < self.max_len_path:input_idx += [self.voc_dict["<PAD>"] for _ in range(self.max_len_path - len(input_idx))]# 转为数组data = np.array(input_idx)return lable, datadef data_loader(dataset,config):# # 微博评论数据路径# data_path = "sources/weibo_senti_100k.csv"# # 停用词路径# data_stop_path = "sources/hit_stopword.txt"# # 字典路径# dict_path = "sources/dict"return DataLoader(dataset, batch_size=config.batch_size, shuffle=config.is_shuffle)#将数据集拆分为小批次,并在训练或推理过程中按批次提供数据。if __name__ == '__main__':# 微博评论数据路径data_path = "sources/weibo_senti_100k.csv"# 停用词路径data_stop_path = "sources/hit_stopword.txt"# 字典路径dict_path = "sources/dict"train_dataloader= data_loader(dict_path,data_path,data_stop_path)for i,batch in enumerate(train_dataloader):print(batch)

config.py 用于配置训练模型

import torchclass Config():def __init__(self):# 词汇表的大小,表示模型可以处理的不同词汇的数量。self.n_vocab = 1002# 词嵌入的维度,即将词索引转换为密集向量表示的维度。self.embed_size = 128# LSTM隐藏状态的维度,决定了模型的记忆容量和表示能力。self.hidden_size = 128# LSTM层的数量,表示堆叠的LSTM层的层数。self.num_layers = 3# 用于控制模型中的dropout概率,以减少过拟合。self.dropout = 0.8# 模型要预测的类别数量。self.num_classes = 2# 输入序列的固定长度,用于处理变长序列的情况。self.pad_size = 32self.batch_size=128self.is_shuffle=Trueself.numepochs = 100#学习率self.learn_rate=0.001# 用于指定模型在哪个设备上运行,如果CUDA可用,则使用GPU进行加速,否则使用CPU。self.devices = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

model.py

import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as npclass Model(nn.Module):# config网络搭建所需要的参数def __init__(self, config):super(Model, self).__init__()# 词嵌入层 将输入序列转化为向量  嵌入层用于将输入的离散化的文本数据转换为连续的稠密向量表示。  嵌入向量通常是随机初始化的,并在训练过程中通过反向传播算法进行优化。# config.n_vocab# 表示词汇表的大小,即输入文本中不同单词的数量。# config.embed_size# 表示嵌入向量的维度,即每个单词表示为一个向量的长度。# padding_idx = config.n_vocab - 1# 表示填充位置的索引,通常用于处理序列长度不一致的情况。这里将最后一个单词的索引设置为填充位置。self.embeding = nn.Embedding(config.n_vocab,config.embed_size,padding_idx=config.n_vocab - 1)# 定义STML层  模型可以对输入的序列数据进行建模和处理,捕捉序列中的长期依赖关系。# LSTM 层在训练过程中会学习到如何根据输入的序列数据生成隐藏状态,并在后续的计算中使用这些隐藏状态。# 输入为词嵌入层的输出,即词向量化之后的结果self.lstm = nn.LSTM(config.embed_size,config.hidden_size,  # 隐藏层节点的数量config.num_layers,  # 使用几个LSTMbidirectional=True,  # 双向STMLbatch_first=True,  # 表示输入数据的批次维度位于第一个位置dropout=config.dropout)  # 随机抑制一些节点,防止过拟合# 定义卷积网络# 是一个实例变量,用于创建一个最大池化层(MaxPool1d)。最大池化层用于对输入数据进行下采样,减少特征图的尺寸。self.maxPool = nn.MaxPool1d(config.pad_size)  # config.pad_size表示池化操作中的填充大小,用于处理输入序列长度不一致的情况。# 定义fc层即线性层 用于创建一个全连接层(Linear)。全连接层用于将之前的特征映射转换为分类输出。self.fc = nn.Linear(config.hidden_size * 2 + config.embed_size,# 表示全连接层的输入维度,由 LSTM 层的隐藏状态维度乘以 2(因为是双向 LSTM)加上词嵌入层的输出维度组成。config.num_classes)  # 表示分类任务的类别数量,即全连接层的输出维度。# Softmax 层用于将全连接层的输出转换为概率分布,表示每个类别的预测概率。self.softmax = nn.Softmax(dim=1)# 模型的前向传播方法,它描述了数据在模型中的流动过程def forward(self, x):# 输出结果[batch_size,seqlen,embed_size]embed = self.embeding(x)  # 将输入通过嵌入层得到密集表示out, _ = self.lstm(embed)  # 将嵌入的输入通过LSTM层得到输出序列out = torch.cat((embed, out), 2)  # 沿特征维度连接嵌入的输入和LSTM输出out = F.relu(out)  # 应用ReLU激活函数out = out.permute(0, 2, 1)  # 调整张量的维度以进行最大池化操作out = self.maxPool(out).reshape(out.size()[0], -1)  # 执行最大池化操作,获得固定大小的可变长度输入表示out = self.fc(out)  # 将池化输出通过全连接层out = self.softmax(out)  # 应用softmax激活函数,得到类别概率return outif __name__ == '__main__':from configs import Configcfg = Config()cfg.pad_size = 640  # 这个参数用于指定输入序列的固定长度。model_textcls = Model(config=cfg)# 创建一个输入张量input_tensor,包含从0到639的索引序列,并将其reshape为形状为[1, 640]的张量。这里使用了列表推导式来生成索引序列。input_tensor = torch.tensor([i for i in range(640)]).reshape([1, 640])out_tensor = model_textcls.forward(input_tensor)print(out_tensor.size())print(out_tensor)

run_train.py

import torch
import torch.nn as nn
from torch import optim  # 导入优化器
from models import Model  # 导入模型
from datasets import data_loader, text_CLS  # 导入数据
from configs import Config  # 导入配置# 创建一个配置对象cfg
cfg = Config()# 微博评论数据路径
data_path = "sources/weibo_senti_100k.csv"
# 停用词路径
data_stop_path = "sources/hit_stopword.txt"
# 字典路径
dict_path = "sources/dict"dataset = text_CLS(dict_path, data_path, data_stop_path)
# 使用data_loader函数创建一个训练数据的数据加载器train_dataloader,用于按批次加载数据。
train_dataloader = data_loader(dataset, cfg)# 将配置对象cfg的pad_size属性设置为数据集的最大序列长度。
cfg.pad_size = dataset.max_len_path# 创建一个模型对象model_text_cls,并将其移动到指定的设备(GPU或CPU)上进行计算。
model_text_cls = Model(config=cfg)
model_text_cls.to(cfg.devices)# 定义损失函数 采用交叉熵
loss_func = nn.CrossEntropyLoss()
# 定义优化器
optimizer = optim.Adam(model_text_cls.parameters(), lr=cfg.learn_rate)flag = 1
# 开始训练
"""
使用嵌套的循环进行模型的训练。外层循环迭代训练的轮数(numepochs),内层循环迭代每个批次的数据。
在每个批次中,将数据和标签转换为张量并移动到指定的设备上。然后,将模型的梯度清零(zero_grad()),
通过调用模型的前向传播方法(forward())获取预测结果,并计算损失值。
接着,通过调用损失函数的backward()方法进行反向传播,计算梯度并更新模型的参数(step())。
"""
for epoch in range(cfg.numepochs):for i, batch in enumerate(train_dataloader):  # 使用enumerate函数获取批次的索引i和对应的数据batch。label, data = batch# 将数据和标签转换为张量,并将它们移动到指定的设备上(GPU或CPU)。data = torch.tensor(data).to(cfg.devices)label = torch.tensor(label, dtype=torch.int64).to(cfg.devices)optimizer.zero_grad()  # 将优化器的梯度缓冲区清零,以便进行下一次反向传播。pred = model_text_cls.forward(data)  # 通过调用模型的前向传播方法,将数据输入模型获得预测结果。loss_val = loss_func(pred, label)  # 使用损失函数计算预测结果与标签之间的损失值。# 打印预测结果# print(pred)# print(label)# print("epoch is {} ,ite is {},val is {}".format(epoch, i, loss_val))loss_val.backward()  # 执行反向传播,计算梯度。optimizer.step()  # 根据计算得到的梯度,更新模型的参数。print(f"完成{flag}次迭代{epoch}")flag += 1if epoch % 20 == 0:print("保存了{}".format(epoch))torch.save(model_text_cls.state_dict(), "models/{}.pth".format(epoch))print("训练完成")

test.py

import torch
import torch.nn as nn
from torch import optim  # 导入优化器
from models import Model  # 导入模型
from datasets import data_loader, text_CLS  # 导入数据
from configs import Config  # 导入配置
#创建一个配置对象cfg
cfg = Config()# 微博评论数据路径
data_path = "sources/weibo_senti_100k.csv"
# 停用词路径
data_stop_path = "sources/hit_stopword.txt"
# 字典路径
dict_path = "sources/dict"dataset = text_CLS(dict_path, data_path, data_stop_path)
#使用data_loader函数创建一个训练数据的数据加载器train_dataloader,用于按批次加载数据。
train_dataloader = data_loader(dataset, cfg)#将配置对象cfg的pad_size属性设置为数据集的最大序列长度。
cfg.pad_size = dataset.max_len_path# 创建一个模型对象model_text_cls,并将其移动到指定的设备(GPU或CPU)上进行计算。
model_text_cls = Model(config=cfg)
model_text_cls.to(cfg.devices)model_text_cls.load_state_dict(torch.load("models"))# 开始训练
"""
使用嵌套的循环进行模型的训练。外层循环迭代训练的轮数(numepochs),内层循环迭代每个批次的数据。
在每个批次中,将数据和标签转换为张量并移动到指定的设备上。然后,将模型的梯度清零(zero_grad()),
通过调用模型的前向传播方法(forward())获取预测结果,并计算损失值。
接着,通过调用损失函数的backward()方法进行反向传播,计算梯度并更新模型的参数(step())。
"""for i, batch in enumerate(train_dataloader): #使用enumerate函数获取批次的索引i和对应的数据batch。label, data = batch#将数据和标签转换为张量,并将它们移动到指定的设备上(GPU或CPU)。data = torch.tensor(data).to(cfg.devices)label = torch.tensor(label, dtype=torch.int64).to(cfg.devices)pred_softmax = model_text_cls.forward(data) #通过调用模型的前向传播方法,将数据输入模型获得预测结果。# 打印预测结果# print(pred_softmax)# print(label)# print("epoch is {} ,ite is {},val is {}".format(epoch, i, loss_val))pred=torch.argmax(pred_softmax,dim=1)# print(pred)out= torch.eq(pred,label)# print(out)print(out.sum()*1.0/pred.size()[0])

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

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

相关文章

MATLAB编译器配置:MinGW

使用 MATLAB 2022b版本&#xff0c;查询编译器时如上&#xff0c;想安装个MinGW编译器&#xff0c;自带的附加资源管理不好使&#xff0c;只能换个别的法子&#xff0c;经过一些参考&#xff0c;总结如下。 步骤1.在这里下载一个MinGW.最新版本是10.3.0.然后默认安装&#xff…

蓝桥杯刷题|03入门真题

目录 [蓝桥杯 2020 省 B1] 整除序列 题目描述 输入格式 输出格式 输入输出样例 说明/提示 代码及思路 [蓝桥杯 2020 省 AB3] 日期识别 题目描述 输入格式 输出格式 输入输出样例 说明/提示 代码及思路 [蓝桥杯 2019 省 B] 特别数的和 题目描述 输入格式 输出格…

谷歌的后量子密码学威胁模型

1. 引言 若现在不使用量子安全算法来加密数据&#xff0c;能够存储当前通信的攻击者最快十年内就能对其解密。这种先存储后解密的攻击是当前采用后量子密码学 (post-quantum cryptography&#xff0c;PQC) 背后的主要动机&#xff0c;但其他未来的量子计算威胁也需要一个深思熟…

GEC6818——QT开发之两个UI界面切换与表格显示DHT11数据

GEC6818——QT开发之两个UI界面切换与表格显示DHT11数据 使用环境: ubantu16 QT5.7 开发板GEC6818 实现要求&#xff1a; 利用A53按键1、按键2与温湿度传感器完成QT界面动态显示温湿度记录&#xff0c;并指定温湿度记录超过指定范围&#xff0c;进行报警&#xff08;LED&#…

天锐绿盾|公司开发部门源代码泄露防护系统,无感透明加密软件

#代码加密、代码防泄密、开发部门源码防泄漏、源代码透明加密、办公透明加密系统# 天锐绿盾作为一款针对企业数据安全的专业软件&#xff0c;特别是在防止公司开发部门源代码泄露方面&#xff0c;提供了智能无感透明加密保护系统。 德人合科技 | 天锐绿盾 PC地址&#xff1a; …

【经验分享】Wubuntu------体验Windows和Ubuntu的结合体

【经验分享】Wubuntu------体验Windows和Ubuntu的结合体 最近看到有一款Wubuntu的文章&#xff0c;对于习惯使用windows操作系统&#xff0c;又不熟悉ubuntu系统的程序员小白来说&#xff0c;可以说是福音了。目前的Wubuntu兼容性可能还有一点问题&#xff0c;如果再迭代几次的…

Python库Gym:打开机器学习与强化学习的大门

Python库Gym&#xff1a;打开机器学习与强化学习的大门 强化学习作为人工智能领域的重要分支&#xff0c;已经在各种领域展现出了巨大的潜力。为了帮助开发者更好地理解和应用强化学习算法&#xff0c;Python库Gym应运而生。Gym提供了一个开放且易于使用的环境&#xff0c;供开…

win电脑安装绿色版MySQL8

一、下载压缩包 下载mysql server的zip文件&#xff0c;地址&#xff1a;Windows (x86, 64-bit), ZIP Archive 解压后&#xff1a; 二、创建配置文件&#xff08;可忽略&#xff09; 配置文件可存放位置及名称&#xff1a; C:\WINDOWS\my.ini C:\WINDOWS\my.cnf C:\my.ini…

招个Java工程师,却发现了一个宝藏平台

一直关注磊哥的朋友都知道&#xff0c;磊哥出来创业&#xff08;做 Java 就业指导&#xff09;也快一年了&#xff0c;从最初的纠结彷徨、不知所措&#xff0c;到现在逐渐找到自己的节奏&#xff0c;也算是半个媳妇熬成婆了。 磊哥现在每天做的事儿&#xff0c;就是通过文章和…

使用Navicat远程连接Linux中的MySQL

一、登录MySQL数据库 mysql -uroot -pXjm123456 二、使用mysql数据库 use mysql&#xff1b; 三、查询user表中包含host的字段 select user,host from user;### 该字段中&#xff0c;localhost表示只允许本机访问&#xff0c;可以将‘localhost’改为‘%’&#xff0c;‘%’表…

8.发布页面

发布页面 官网 https://vkuviewdoc.fsq.pub/components/form.html 复制官网中的内容 代码 write.vue <template><view class"u-wrap u-p-l-20 u-p-r-20"><u-form :model"addModel" ref"form1"><u-form-item label&quo…

深度强化学习06Actor-Critic

Critic裁判 裁判打分 提高自己的技术 提高打分水平

编译原理-实现识别标识符的词法分析器——沐雨先生

实验任务&#xff1a; 实现识别标识符的词法分析器 实验要求&#xff1a; 根据编译原理理论课教材中图2.3“标识符的转换图”&#xff0c;用C语言编写识别标识符的词法分析器&#xff0c;以文本文件为输入&#xff0c;控制台&#xff08;或文件&#xff09;输出识别出的每个…

uni app 打肉肉(打飞机)小游戏

都给老婆和孩子写了 合十 钓鱼了&#xff0c;给自己写个打飞机吧。没找飞机怪兽的图片。就用馒头和肉肉代替了。有问题不要私信我。自己改哈 <template><view class"page_main"><view class"contentone"><canvas class"canvas…

C语言每日一题(64)快乐数

题目链接 力扣网202 快乐数 题目描述 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不…

Flink源码解析(1)job启动,从JM到TM过程详解

网络传输模型 首先在看之前,回顾一下akka模型: Flink通讯模型—Akka与Actor模型-CSDN博客 注:ActorRef就是actor的引用,封装好了actor 下面是jm和tm在通讯上的概念图: RpcGateway 不理解网关的作用,可以先移步看这里:网关_百度百科 (baidu.com) 用于定义RPC协议,是…

torchvision pytorch预训练模型目标检测使用

参考&#xff1a; https://pytorch.org/vision/0.13/models.html https://blog.csdn.net/weixin_42357472/article/details/131747022 有分类、检测、分割相关预训练模型 1、目标检测 https://pytorch.org/vision/0.13/models.html#object-detection-instance-segmentation-…

四.流程控制(顺序,分支,循环,嵌套)

c刚刚转过来的记得写在public static void main&#xff08;String[] args&#xff09;的花括号里 一.顺序结构 二.分支结构 if &#xff0c;switch 1.if (条件判断&#xff09; 2.if else 3.if else if else if ... else(它是一个一个否定来一个个执行判断的 4.s…

day-24 腐烂的橘子

思路&#xff1a;利用bfs的思想 首先利用bfs遍历值为2的橘子&#xff08;遍历时1和2都可以走&#xff09;结束后如果存在某个橘子未被访问过且值为1则返回-1 再利用bfs遍历值为2的橘子 每遍历一次 时间加1 注意不要立即将map的值变为2&#xff0c;可以通过一个缓存数组临时存放…

CentOS7使用Docker部署.net Webapi

1 准备WebApi项目 对于已存在的WebApi项目&#xff0c;需要添加Docker支持&#xff1b; 编码时&#xff0c;先设置好项目需要的端口号&#xff1a;program.cs中&#xff0c;app.Run("http://*:8000");设置端口为&#xff1a;8000在VS中&#xff0c;选中项目&#xf…