NLP(12)--语言模型

前言

仅记录学习过程,有问题欢迎讨论

应用-语音识别:
  • 声音的本质是一种,将波按时间段切分为很多,之后进行声学特征提取,每一帧转化为向量。

应用-输入法:

  • 按照语言模型给出概率最高的候选词

语言模型的分类:

  • 统计语言模型 (SLM) S = Statistics: ngram语言模型等(成句概率)

    • 马尔可夫假设:假设第n个词出现的概率,仅受其前面 “有限” 个词的影响

    • 平滑(折扣)问题:遇见没见过的句子,概率也不应该为0

    • 解决方案–回退:当三元组abc未出现时,找bc二元组的概率(* 概率值 0.4)

    • PPL(判断标准) : 困惑度 和 成句概率成反比----相对值

  • 神经语言模型(NLM) N = Neural: rnn语言模型等

    • 语言模型的核心能力是计算成句概率(打标点符号,数字归一化,文本纠错)
    • 效果比统计类型好,但是速度相对没它这么快
  • 预训练语言模型(PLM) P = Pre-train: Bert、GPT等

    • self_attention:文本中每个字 和其他字之间的关系(注意力越高,关系越密切) Q*K.(T) 和RNN相比,不会遗忘之前的信息,每个字都有其他字的相关信息。
    • 多头机制:10 * 768 ==> (embedding_dim, num_heads * head_dim),然后吧KQV的每个第n组计算self—attention 然后拼接回来变为 10 * 768( 相当于每次同时训练了12个模型,汇总结果)

在这里插入图片描述

  • 大语言模型(LLM) L = Large: ChatGPT等

代码

n-gram 统计型demo

import math
from collections import defaultdictclass NgramLanguageModel:def __init__(self, corpus=None, n=3):self.n = nself.sep = "_"  # 用来分割两个词,没有实际含义,只要是字典里不存在的符号都可以self.sos = "<sos>"  # start of sentence,句子开始的标识符self.eos = "<eos>"  # end of sentence,句子结束的标识符self.unk_prob = 1e-5  # 给unk分配一个比较小的概率值,避免集外词概率为0self.fix_backoff_prob = 0.4  # 使用固定的回退概率self.ngram_count_dict = dict((x + 1, defaultdict(int)) for x in range(n))self.ngram_count_prob_dict = dict((x + 1, defaultdict(int)) for x in range(n))self.ngram_count(corpus)self.calc_ngram_prob()# 将文本切分成词或字或tokendef sentence_segment(self, sentence):return sentence.split()# return jieba.lcut(sentence)# 统计ngram的数量def ngram_count(self, corpus):for sentence in corpus:word_lists = self.sentence_segment(sentence)word_lists = [self.sos] + word_lists + [self.eos]  # 前后补充开始符和结尾符for window_size in range(1, self.n + 1):  # 按不同窗长扫描文本for index, word in enumerate(word_lists):# 取到末尾时窗口长度会小于指定的gram,跳过那几个if len(word_lists[index:index + window_size]) != window_size:continue# 用分隔符连接word形成一个ngram用于存储ngram = self.sep.join(word_lists[index:index + window_size])self.ngram_count_dict[window_size][ngram] += 1# 计算总词数,后续用于计算一阶ngram概率self.ngram_count_dict[0] = sum(self.ngram_count_dict[1].values())return# 计算ngram概率def calc_ngram_prob(self):for window_size in range(1, self.n + 1):for ngram, count in self.ngram_count_dict[window_size].items():if window_size > 1:ngram_splits = ngram.split(self.sep)  # ngram        :a b cngram_prefix = self.sep.join(ngram_splits[:-1])  # ngram_prefix :a bngram_prefix_count = self.ngram_count_dict[window_size - 1][ngram_prefix]  # Count(a,b)else:ngram_prefix_count = self.ngram_count_dict[0]  # count(total word)# word = ngram_splits[-1]# self.ngram_count_prob_dict[word + "|" + ngram_prefix] = count / ngram_prefix_countself.ngram_count_prob_dict[window_size][ngram] = count / ngram_prefix_countreturn# 获取ngram概率,其中用到了回退平滑,回退概率采取固定值def get_ngram_prob(self, ngram):n = len(ngram.split(self.sep))if ngram in self.ngram_count_prob_dict[n]:# 尝试直接取出概率return self.ngram_count_prob_dict[n][ngram]elif n == 1:# 一阶gram查找不到,说明是集外词,不做回退return self.unk_probelse:# 高于一阶的可以回退ngram = self.sep.join(ngram.split(self.sep)[1:])return self.fix_backoff_prob * self.get_ngram_prob(ngram)# 回退法预测句子概率def calc_sentence_ppl(self, sentence):word_list = self.sentence_segment(sentence)word_list = [self.sos] + word_list + [self.eos]sentence_prob = 0for index, word in enumerate(word_list):ngram = self.sep.join(word_list[max(0, index - self.n + 1):index + 1])prob = self.get_ngram_prob(ngram)# print(ngram, prob)sentence_prob += math.log(prob)return 2 ** (sentence_prob * (-1 / len(word_list)))if __name__ == "__main__":corpus = open("sample.txt", encoding="utf8").readlines()lm = NgramLanguageModel(corpus, 3)print("词总数:", lm.ngram_count_dict[0])print(lm.ngram_count_prob_dict)print(lm.calc_sentence_ppl("c d b d b"))

rnn demo 预测句子的分类
(需要语料可留言)

import torch
import torch.nn as nn
import math
import os
import random
import torch.utils.data as data_util
import numpy as np"""
import torch
import torch.nn as nn
import math
import os
import random
import torch.utils.data as data_util
import numpy as np"""week 6--语言模型
通俗来说就是人话统计语言模型----=N-gram
成句概率-》 词w1--wn 按顺序出现的概率
马尔可夫假设:假设第n个词出现的概率,仅受其前面  “有限”  个词的影响P(今天天气不错) = P()*P(|) *P(|今天) *P(|天天) *P(|天气) *P(|气不)平滑(折扣)问题
遇见没见过的句子,概率也不应该为0
解决方案:回退:当三元组abc未出现时,找bc二元组的概率(* 概率值 0.4)若是P(word) 都不存在:  加1平滑(count数+1/// 低频词替换为【unk】 都当做<unk>处理插值:计算高阶的概率时,同时考虑低阶的概率 Pw1|wn-1 wn-2 = aP(w1|wn-1 wn-2) + bp(w1|wn-1) + cP(wn)PPL : 困惑度 和 成句概率成反比----相对值"""# 实现一个判断文本是否该领域的模型 根据ppl大小
class LanguageModel(nn.Module):def __init__(self, input_dim, vocab):super(LanguageModel, self).__init__()self.emb = nn.Embedding(len(vocab) + 1, input_dim)self.rnn = nn.RNN(input_dim, input_dim, batch_first=True)# 输出为字表的长度 代表可能性为任何一个字 因为是预测self.linear = nn.Linear(input_dim, len(vocab) + 1)self.drop = nn.Dropout(0.1)self.loss = nn.functional.cross_entropydef forward(self, x, y=None):x = self.emb(x)  # output shape:(batch_size, sen_len, input_dim)x, _ = self.rnn(x)  # output shape:(batch_size, sen_len, input_dim)# x 取最后一个x = x[:, -1, :]  # output shape:(batch_size, input_dim)x = self.drop(x)y_pred = self.linear(x)if y is not None:return self.loss(y_pred, y)  # [1*vocab_size] []else:# 需要归一化处理return torch.softmax(y_pred, dim=-1)def build_vocab(vocab_path):# set dictvocab = {}with open(vocab_path, encoding="utf8") as f:for index, line in enumerate(f):char = line[:-1]  # 去掉结尾换行符vocab[char] = index + 1  # 留出0位给pad tokenvocab["\n"] = 1return vocabdef build_simple(corpus, window_size, vocab):start = random.randint(0, len(corpus) - 1 - window_size)end = start + window_sizewindow = corpus[start:end]# 窗口后一个字符target = corpus[end]x = [vocab.get(char, vocab["<UNK>"]) for char in window]y = vocab[target]return x, ydef build_dataset(simple_size, corpus, window_size, vocab):x = []y = []for i in range(simple_size):dataset_x, dataset_y = build_simple(corpus, window_size, vocab)x.append(dataset_x)y.append(dataset_y)return torch.LongTensor(x), torch.LongTensor(y)# 读取文件
def load_corpus(corpus_path):return open(corpus_path, encoding="utf8").read()def train(corpus_path, save_weight=True):epoch_num = 10  # 训练轮数batch_size = 128  # 每次训练样本个数train_sample = 10000  # 每轮训练总共训练的样本总数char_dim = 128  # 每个字的维度window_size = 6  # 样本文本长度vocab = build_vocab("D:\\NLP\\test\\week6\\vocab.txt")  # 建立字表corpus = load_corpus(corpus_path)  # 加载语料model = LanguageModel(char_dim, vocab)  # 建立模型x, y = build_dataset(train_sample, corpus, window_size, vocab)dataset = data_util.TensorDataset(x, y)dataiter = data_util.DataLoader(dataset, batch_size)# gpuif torch.cuda.is_available():model = model.cuda()optim = torch.optim.Adam(model.parameters(), lr=0.001)  # 建立优化器for epoch in range(epoch_num):# start trainingmodel.train()epoch_loss = []# x.shape == 20*5 y_true.shape == 20for x, y_true in dataiter:# print(x, y_true)# 交叉熵需要传递整个x,y过去,而非单个的loss = model(x, y_true)# print(loss)# 反向传播过程,在反向传播过程中会计算每个参数的梯度值loss.backward()# 改變權重;所有的 optimizer 都实现了 step() 方法,该方法会更新所有的参数。optim.step()# 将上一轮计算的梯度清零,避免上一轮的梯度值会影响下一轮的梯度值计算optim.zero_grad()epoch_loss.append(loss.data)print("=========\n第%d轮平均loss:%f" % (epoch + 1, np.mean(epoch_loss)))if not save_weight:returnelse:base_name = os.path.basename(corpus_path).replace("txt", "pth")model_path = os.path.join("D:\\NLP\\test\\week6\\model", base_name)torch.save(model.state_dict(), model_path)returndef train_all():for path in os.listdir("../week6/corpus"):corpus_path = os.path.join("D:\\NLP\\test\\week6\\corpus", path)print(corpus_path)train(corpus_path)# def cal_ppl(sentence, model, vocab, window_size):
#     prob = 0
#     model.eval()
#     with torch.no_grad():
#         for i in range(1, len(sentence)):
#             start = max(0, i - window_size)
#             window = sentence[start:i]
#             x = [vocab.get(char, vocab["<UNK>"]) for char in window]
#             x = torch.LongTensor([x])
#             target = sentence[i]
#             target_index = vocab.get(target, vocab["<UNK>"])
#             if torch.cuda.is_available():
#                 x = x.cuda()
#             pred_prob_distribute = model(x)[0]
#             target_prob = pred_prob_distribute[target_index]
#             prob += math.log(target_prob, 10)
#     return 2 ** (prob * (-1 / len(sentence)))# 计算文本ppl (rnn 无需回退 因为输出的softmax自带平滑)
def cal_ppl(sentence, model):prob = 0with torch.no_grad():for i in range(1, len(sentence)):start = max(0, i - model.window_size)window = sentence[start:i]x = [model.vocab.get(char, model.vocab["<UNK>"]) for char in window]x = torch.LongTensor([x])target = sentence[i]# 目标值的下标target_index = model.vocab.get(target, model.vocab["<UNK>"])if torch.cuda.is_available():x = x.cuda()pred_prob_distribute = model(x)[0]# 对应的概率是多少target_prob = pred_prob_distribute[target_index]# print(window , "->", target, "prob:", float(target_prob))prob += math.log(target_prob, 10)return 2 ** (prob * (-1 / len(sentence)))
# if __name__ == '__main__':
#     train_all()# ============================== implement =============================
def load_trained_language_model(path):char_dim = 128  # 每个字的维度,与训练时保持一致window_size = 6  # 样本文本长度,与训练时保持一致vocab = build_vocab("D:\\NLP\\test\\week6\\vocab.txt")  # 加载字表model = LanguageModel(char_dim, vocab)  # 加载模型model.load_state_dict(torch.load(path))  # 加载训练好的模型权重model.eval()if torch.cuda.is_available():model = model.cuda()model.window_size = window_sizemodel.vocab = vocabreturn model# 加载训练好的所有模型
def load_models():model_paths = os.listdir("D:\\NLP\\test\\week6\\model")class_to_model = {}for model_path in model_paths:class_name = model_path.replace(".pth", "")model_path = os.path.join("D:\\NLP\\test\\week6\\model", model_path)class_to_model[class_name] = load_trained_language_model(model_path)return class_to_model# 基于语言模型的文本分类伪代码
# class_to_model: {"class1":<language model obj1>, "class2":<language model obj2>, ..}
# 每个语言模型,用对应的领域语料训练
def text_classification_based_on_language_model(class_to_model, sentence):ppl = []for class_name, class_lm in class_to_model.items():# 用每个语言模型计算pplppl.append([class_name, cal_ppl(sentence, class_lm)])ppl = sorted(ppl, key=lambda x: x[1])print(sentence)print(ppl[0: 3])print("==================")return pplsentence = ["在全球货币体系出现危机的情况下","点击进入双色球玩法经典选号图表","慢时尚服饰最大的优点是独特","做处女座朋友的人真的很难","网戒中心要求家长全程陪护","在欧巡赛扭转了自己此前不利的状态","选择独立的别墅会比公寓更适合你",]class_to_model = load_models()
for s in sentence:text_classification_based_on_language_model(class_to_model, s)

plm Demo bert: 要理解其中参数维度的变化

import torch
import math
import numpy as np
from transformers import BertModel'''通过手动矩阵运算实现Bert结构
模型文件下载 https://huggingface.co/models'''bert = BertModel.from_pretrained(r"D:\NLP\video\第六周\bert-base-chinese", return_dict=False)
state_dict = bert.state_dict()
bert.eval()
x = np.array([2450, 15486, 102, 2110])  # 通过vocab对应输入:深度学习
torch_x = torch.LongTensor([x])  # pytorch形式输入
# 所有字符的向量 ,开头的cls(包含所有字符信息)
# 1 * 4 * 768(simple_size * list_size * input_dim)   1 * 768(simple_size* input_dim)
seqence_output, pooler_output = bert(torch_x)
print(seqence_output.shape, pooler_output.shape)# print(seqence_output, pooler_output)
# 答案
# print(bert.state_dict().keys())  #查看所有的权值矩阵名称# input()# softmax归一化
def softmax(x):return np.exp(x) / np.sum(np.exp(x), axis=-1, keepdims=True)# gelu激活函数
def gelu(x):return 0.5 * x * (1 + np.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * np.power(x, 3))))class DiyBert:# 将预训练好的整个权重字典输入进来def __init__(self, state_dict):# 多头self.num_attention_heads = 12self.hidden_size = 768# should be 12self.num_layers = 1self.load_weights(state_dict)def load_weights(self, state_dict):# embedding部分#     output:21128 * 768(vocab_size * setence_dim)self.word_embeddings = state_dict["embeddings.word_embeddings.weight"].numpy()# 位置  output:512(max) *768self.position_embeddings = state_dict["embeddings.position_embeddings.weight"].numpy()# 同一句话对应的向量一致 [output:2(type_vocab_size) *768](不过一句话的值一致) segmentself.token_type_embeddings = state_dict["embeddings.token_type_embeddings.weight"].numpy()# 激活层(归一化)output: 1 * 768self.embeddings_layer_norm_weight = state_dict["embeddings.LayerNorm.weight"].numpy()#output: 1 * 768self.embeddings_layer_norm_bias = state_dict["embeddings.LayerNorm.bias"].numpy()self.transformer_weights = []# transformer部分,有多层for i in range(self.num_layers):# output: 768* (12*64)(embedding_dim, num_heads * head_dim)q_w = state_dict["encoder.layer.%d.attention.self.query.weight" % i].numpy()q_b = state_dict["encoder.layer.%d.attention.self.query.bias" % i].numpy()# output: 768* 768k_w = state_dict["encoder.layer.%d.attention.self.key.weight" % i].numpy()k_b = state_dict["encoder.layer.%d.attention.self.key.bias" % i].numpy()# output: 768* 768v_w = state_dict["encoder.layer.%d.attention.self.value.weight" % i].numpy()v_b = state_dict["encoder.layer.%d.attention.self.value.bias" % i].numpy()# 过一个线性层  output:768* 768attention_output_weight = state_dict["encoder.layer.%d.attention.output.dense.weight" % i].numpy()attention_output_bias = state_dict["encoder.layer.%d.attention.output.dense.bias" % i].numpy()# 过一个归一化 output:1*768attention_layer_norm_w = state_dict["encoder.layer.%d.attention.output.LayerNorm.weight" % i].numpy()attention_layer_norm_b = state_dict["encoder.layer.%d.attention.output.LayerNorm.bias" % i].numpy()# 变大的layer层   output:3072*768intermediate_weight = state_dict["encoder.layer.%d.intermediate.dense.weight" % i].numpy()intermediate_bias = state_dict["encoder.layer.%d.intermediate.dense.bias" % i].numpy()# 变回来的layer层===》output: 768* 3072output_weight = state_dict["encoder.layer.%d.output.dense.weight" % i].numpy()output_bias = state_dict["encoder.layer.%d.output.dense.bias" % i].numpy()# 激活层 output: 768ff_layer_norm_w = state_dict["encoder.layer.%d.output.LayerNorm.weight" % i].numpy()ff_layer_norm_b = state_dict["encoder.layer.%d.output.LayerNorm.bias" % i].numpy()self.transformer_weights.append([q_w, q_b, k_w, k_b, v_w, v_b, attention_output_weight, attention_output_bias,attention_layer_norm_w, attention_layer_norm_b, intermediate_weight, intermediate_bias,output_weight, output_bias, ff_layer_norm_w, ff_layer_norm_b])# pooler层self.pooler_dense_weight = state_dict["pooler.dense.weight"].numpy()self.pooler_dense_bias = state_dict["pooler.dense.bias"].numpy()# bert embedding,使用3层叠加,在经过一个embedding层def embedding_forward(self, x):# x.shape = [max_len]we = self.get_embedding(self.word_embeddings, x)  # shpae: [max_len, hidden_size]# position embeding的输入 [0, 1, 2, 3]pe = self.get_embedding(self.position_embeddings,np.array(list(range(len(x)))))  # shpae: [max_len, hidden_size]# token type embedding,单输入的情况下为[0, 0, 0, 0]te = self.get_embedding(self.token_type_embeddings, np.array([0] * len(x)))  # shpae: [max_len, hidden_size]embedding = we + pe + te# 加和后有一个归一化层embedding = self.layer_norm(embedding, self.embeddings_layer_norm_weight,self.embeddings_layer_norm_bias)  # shpae: [max_len, hidden_size]return embedding# embedding层实际上相当于按index索引,或理解为onehot输入乘以embedding矩阵def get_embedding(self, embedding_matrix, x):return np.array([embedding_matrix[index] for index in x])# 执行全部的transformer层计算def all_transformer_layer_forward(self, x):for i in range(self.num_layers):x = self.single_transformer_layer_forward(x, i)return x# 执行单层transformer层计算def single_transformer_layer_forward(self, x, layer_index):weights = self.transformer_weights[layer_index]# 取出该层的参数,在实际中,这些参数都是随机初始化,之后进行预训练q_w, q_b, \k_w, k_b, \v_w, v_b, \attention_output_weight, attention_output_bias, \attention_layer_norm_w, attention_layer_norm_b, \intermediate_weight, intermediate_bias, \output_weight, output_bias, \ff_layer_norm_w, ff_layer_norm_b = weights# self attention层attention_output = self.self_attention(x,q_w, q_b,k_w, k_b,v_w, v_b,attention_output_weight, attention_output_bias,self.num_attention_heads,self.hidden_size)# bn层,并使用了残差机制x = self.layer_norm(x + attention_output, attention_layer_norm_w, attention_layer_norm_b)# feed forward层feed_forward_x = self.feed_forward(x,intermediate_weight, intermediate_bias,output_weight, output_bias)# bn层,并使用了残差机制x = self.layer_norm(x + feed_forward_x, ff_layer_norm_w, ff_layer_norm_b)return x# self attention的计算def self_attention(self,x,q_w,q_b,k_w,k_b,v_w,v_b,attention_output_weight,attention_output_bias,num_attention_heads,hidden_size):# x.shape = max_len * hidden_size# q_w, k_w, v_w  shape = hidden_size * hidden_size# q_b, k_b, v_b  shape = hidden_sizeq = np.dot(x, q_w.T) + q_b  # shape: [max_len, hidden_size]      W * X + B lINERk = np.dot(x, k_w.T) + k_b  # shpae: [max_len, hidden_size]v = np.dot(x, v_w.T) + v_b  # shpae: [max_len, hidden_size]attention_head_size = int(hidden_size / num_attention_heads)# q.shape = num_attention_heads, max_len, attention_head_sizeq = self.transpose_for_scores(q, attention_head_size, num_attention_heads)# k.shape = num_attention_heads, max_len, attention_head_sizek = self.transpose_for_scores(k, attention_head_size, num_attention_heads)# v.shape = num_attention_heads, max_len, attention_head_sizev = self.transpose_for_scores(v, attention_head_size, num_attention_heads)# qk.shape = num_attention_heads, max_len, max_lenqk = np.matmul(q, k.swapaxes(1, 2))qk /= np.sqrt(attention_head_size)qk = softmax(qk)# qkv.shape = num_attention_heads, max_len, attention_head_sizeqkv = np.matmul(qk, v)# qkv.shape = max_len, hidden_sizeqkv = qkv.swapaxes(0, 1).reshape(-1, hidden_size)# attention.shape = max_len, hidden_sizeattention = np.dot(qkv, attention_output_weight.T) + attention_output_biasreturn attention# 多头机制def transpose_for_scores(self, x, attention_head_size, num_attention_heads):# hidden_size = 768  num_attent_heads = 12 attention_head_size = 64max_len, hidden_size = x.shapex = x.reshape(max_len, num_attention_heads, attention_head_size)# 就是 转置x = x.swapaxes(1, 0)  # output shape = [num_attention_heads, max_len, attention_head_size]return x# 前馈网络的计算def feed_forward(self,x,intermediate_weight,  # intermediate_size, hidden_sizeintermediate_bias,  # intermediate_sizeoutput_weight,  # hidden_size, intermediate_sizeoutput_bias,  # hidden_size):# output shpae: [max_len, intermediate_size]x = np.dot(x, intermediate_weight.T) + intermediate_biasx = gelu(x)# output shpae: [max_len, hidden_size]x = np.dot(x, output_weight.T) + output_biasreturn x# 归一化层def layer_norm(self, x, w, b):x = (x - np.mean(x, axis=1, keepdims=True)) / np.std(x, axis=1, keepdims=True)x = x * w + breturn x# 链接[cls] token的输出层def pooler_output_layer(self, x):x = np.dot(x, self.pooler_dense_weight.T) + self.pooler_dense_biasx = np.tanh(x)return x# 最终输出def forward(self, x):x = self.embedding_forward(x)sequence_output = self.all_transformer_layer_forward(x)pooler_output = self.pooler_output_layer(sequence_output[0])return sequence_output, pooler_output# 自制
db = DiyBert(state_dict)
diy_sequence_output, diy_pooler_output = db.forward(x)
# torch
torch_sequence_output, torch_pooler_output = bert(torch_x)print(diy_sequence_output)
print(torch_sequence_output)# print(diy_pooler_output)
# print(torch_pooler_output)

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

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

相关文章

2024年化学材料、清洁能源与生物技术国际学术会议(ICCMCEB2024)

2024年化学材料、清洁能源与生物技术国际学术会议(ICCMCEB2024) 会议简介 2024国际化学材料、清洁能源和生物技术大会&#xff08;ICCMCEB2024&#xff09;将在长沙隆重举行。本次会议旨在汇聚来自世界各地的化学材料、清洁能源和生物技术领域的专家学者&#xff0c;共同探…

用C++译密码

为使电文保密&#xff0c;往往按一定规律将电文转换成密码&#xff0c;收报人再按约定的规律将其译回原文。例如&#xff0c;可以按以下规律将电文变成密码&#xff1a;将字母A变成字母E,a变成e&#xff0c;即变成其后的第4个字母&#xff0c;W变成A,X变成B,Y变成C,Z变成D。字母…

【吃透Java手写】3-SpringBoot-简易版-源码解析

【吃透Java手写】SpringBoot-简易版-源码解析 1 SpringbootDemo2 准备工作2.1 Springboot-my2.1.1 依赖2.1.2 SpringBootApplication2.1.3 SJBSpringApplication2.1.3.1 run方法 2.2 Springboot-user2.2.1 依赖2.2.2 UserController2.2.3 UserApplication 2.3 分析run方法的逻辑…

Vue+OpenLayers7入门到实战:OpenLayers实现鼠标拖拽方式绘制矩形(正方形和长方形)

返回《Vue+OpenLayers7》专栏目录:Vue+OpenLayers7入门到实战 前言 本章介绍如何使用OpenLayers7在地图上实现鼠标拖拽方式绘制矩形(拖拽方式长方形和正方形)。 OpenLayers本身是可以通过鼠标点击多个点的方式来绘制多边形的,当然也包括长方形和正方形,但是这种多边形绘…

Ollama + Openwebui 本地部署大型模型与交互式可视化聊天

Ollama简介 Ollama是一个创新的平台&#xff0c;它允许用户在本地启动并运行大型语言模型。它提供了一个简单易用的内容生成接口&#xff0c;类似于OpenAI&#xff0c;但无需开发经验即可直接与模型进行交互。Ollama支持热切换模型&#xff0c;为用户提供了灵活性和多样性。 …

港股开启估值修复行情 珠光效果材料龙头大涨25%

进入二季度以来&#xff0c;港股市场持续大涨&#xff0c;仅4月恒生指数就大涨7.4%&#xff0c;5月涨幅继续扩大至12.31%&#xff0c;大幅跑赢全球各主要指数。尤其是随着恒生科技多年以来的估值底部的确认&#xff0c;至此恒生指数、恒生港股通&#xff0c;恒生高股息&#xf…

使用C语言实现杨氏矩阵并找出数字

前言 过了五一假期&#xff0c;咋们经过了一个假期的休息&#xff0c;要继续学习了&#xff0c;不能偷懒哦&#xff01;&#xff01; 今天让我们来看看如何在一个杨氏矩阵中找出自己想找到的数字。 首先&#xff0c;我们要了解一下杨氏矩阵到底是什么&#xff0c;如果一个矩阵中…

概念解析 | ROC曲线:评估分类模型

注1:本文系"概念解析"系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:ROC曲线的含义和绘制 概念解析 | ROC曲线:评估分类模型 第一部分:通俗解释 在我们的日常生活中,经常会遇到需要做出判断和选择的情况。比如,当你收到一封邮件时…

深度学习(算法工程师)最火的就业方向

自动驾驶与智能交通 自动驾驶是深度学习技术的一个重要应用领域&#xff0c;其目标是实现车辆的自主导航和驾驶。自动驾驶系统需要借助深度学习技术来识别交通信号、行人、车辆等环境信息&#xff0c;并做出相应的决策。因此&#xff0c;自动驾驶与智能交通领域的就业方向包括…

WPS二次开发系列:一文快速了解WPS SDK功能场景

作者持续关注 WPS二次开发专题系列&#xff0c;持续为大家带来更多有价值的WPS开发技术细节&#xff0c;如果能够帮助到您&#xff0c;请帮忙来个一键三连&#xff0c;更多问题请联系我&#xff08;QQ:250325397&#xff09; 目录 SDK功能介绍 功能详解&#xff1a; 打开文档…

第十二届蓝桥杯省赛真题 Java B 组【原卷】

文章目录 发现宝藏【考生须知】试题 A: ASC试题 B : 卡片试题 C: 直线试题 D: 货物摆放试题 E: 路径试题 F: 时间显示试题 G: 最少砝码试题 H: 杨辉三角形试题 I: 双向排序试题 J: 括号序列 发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;…

echarts指标盘属性概括

echarts指标盘属性概括 代码 有模拟数据可以直接使用const options {animation: true,title: {top: "35%",left: "center",// text: "单元测试覆盖度", // 主标题itemGap: 15,textStyle: {// 主标题样式color: "#666666",fontSize:…

YOLOv5改进 | 独家创新篇 | 利用MobileNetV4的UIB模块二次创新C3(全网独家首发)

一、本文介绍 本文给大家带来的改进机制是利用MobileNetV4的UIB模块二次创新C3&#xff0c;其中UIB模块来自2024.5月发布的MobileNetV4网络&#xff0c;其是一种高度优化的神经网络架构&#xff0c;专为移动设备设计。它最新的改动总结主要有两点&#xff0c;采用了通用反向瓶…

微同城小程序源码 轻松制作本地生活活动赚钱 带完整的安装代码包以及搭建教程

近年来&#xff0c;本地生活服务市场蓬勃发展&#xff0c;人们对于周边的生活信息、活动资讯等需求日益增长。然而&#xff0c;传统的信息发布方式存在诸多不便&#xff0c;如信息更新不及时、传播范围有限等。微同城小程序源码应运而生。它利用小程序的便捷性和普及性&#xf…

海睿思受邀参加 “走进中节能”研习交流,探索新能源数据治理的创新路径

近日&#xff0c;OceanMind海睿思参加由江苏省企业信息化协会&#xff08;以下简称“苏信会”&#xff09;主办的“走进中节能太阳能科技&#xff08;镇江&#xff09;有限公司”研习交流活动。 海睿思与苏美达、远东控股、隆基乐叶、固德威、上能电气等40多位来自制造业领域的…

04-25 周四 FastBuild重构实践-TLS、全局捕获异常、一键配置

04-25 周四 FastBuild重构实践 时间版本修改人描述04-25V0.1宋全恒新建文档2024年5月6日14:33:16V1.0宋全恒完成文档撰写 简介 由于 04-22 周日 阿里云-瑶光上部署FastBuild过程(配置TLS、自定义辅助命令)描述了重新部署一个FastBuild实例的过程&#xff0c;通过阅读这个&…

怎么设置付费视频课程_在线教育知识付费系统

在信息爆炸的时代&#xff0c;我们每天都被海量的信息包围。然而&#xff0c;真正有价值、能够让我们快速提升的知识&#xff0c;往往隐藏在这些信息的深海之中。今天&#xff0c;我要为大家介绍的&#xff0c;就是这样一份珍贵的宝藏——我们的付费视频课程。 工具/原料 微信…

手把手教你微调Stable Diffusion

温馨提示 关于本文&#xff1a; 本文你可以学习到完整的不使用webui借助lora和dreambooth微调Stable Diffusion的全过程。 手把手教你微调Stable Diffusion生成优弧&#xff0c;但是半失败版&#x1f602; 关于训练&#xff1a; 单卡32GV100进行的微调&#xff0c;因为一些…

【leetcode】数学位数题总结

涉及题型&#xff1a;两数相加问题、大数溢出等 相加问题 根据题意定义rs的数据结构判断是存储方式是正序还是逆序&#xff0c;如果是正序需要反转 比如 123 12 135是正序&#xff0c; 321 21 135是逆序反转的方式&#xff1a;对于可以从后往前遍历的&#xff08;如字符串…

高效工作之软件系统——数据结构登记表

数据结构模板 开发完软件系统后&#xff0c;往往需要进行一些登记——《软件系统数据结构登记表》 然后软件项目有60个表左右&#xff0c;难道需要手动录入&#xff0c;那肯定不可能 工欲善其事必先利其器&#xff01;go。。。同事给的模板是下图 效果图 于是想到 之前使用…