龙华区住房和建设局官方网站/指数工具
文章目录
- 引言
- 1. 什么是语言模型
- 2. 语言模型的主要用途
- 2.1 言模型-语音识别
- 2.2 语言模型-手写识别
- 2.3 语言模型-输入法
- 3. 语言模型的分类
- 4. N-gram语言模型
- 4.1 N-gram语言模型-平滑方法
- 4.2 ngram代码
- 4.3 语言模型的评价指标
- 4.4 两类语言模型的对比
- 5. 神经网络语言模型
- 6. 语言模型的应用
- 6.1 语言模型的应用-话者分离
- 6.2 语言模型的应用-文本纠错
- 6.3 语言模型的应用-数字归一化
- 6.4 语言模型的应用-文本打标
- 7. 总结
引言
语言模型是一种用于预测文本序列中下一个词或字符的概率分布的模型。它可以捕获语言结构的某些方面,如语法、句式和上下文信息。传统的语言模型通常使用N-gram方法或隐藏马尔可夫模型,但这些模型往往不能捕捉到长距离依赖和复杂的语义信息。
1. 什么是语言模型
通俗来讲
语言模型评价一句话是否“合理”或“是人话”
数学上讲
P(今天天气不错) > P(今错不天天气)
语言模型用于计算文本的成句概率
2. 语言模型的主要用途
2.1 言模型-语音识别
- 语音识别:声音 -> 文本
- 声音本质是一种波
- 将波按时间段切分很多帧,如25ms一段
- 之后进行声学特征提取,将每一帧转化成一个向量
- 以声学特征提取后的向量为输入,经过声学模型,预测得到音素
- 音素与拼音类似,但要考虑声调
- 音素序列对应多条文本序列,由语言模型挑选出成句概率最高的序列
- 使用beam search或维特比的方式解码
- 语音识别示意图
2.2 语言模型-手写识别
- 识别模型将图片中文字转化为候选汉字(一般分定位和识别两步),再有语言模型挑选出成句概率最高的序列
2.3 语言模型-输入法
- 输入即为拼音序列,每个拼音自然的有多个候选汉字,根据语言模型挑选高概率序列
- 输入法是一个细节繁多的任务,在语言模型这一基础算法上,需要考虑常见的打字手误,常见误读,拼音缩略,中英混杂,输出符号,用户习惯等能力
- 手写输入法,语音输入法同理
3. 语言模型的分类
- 基于统计语言模型
- 对于一份语料进行词频、词序、词共现的统计
- 计算相关概率得到语言模型
- 代表:N-gram语言模型
- 基于神经网络的语言模型
- 根据设定好的网络结构使用语料进行模型训练
- 代表:LSTM语言模型,BERT等
- 自回归(auto regressive)语言模型
- 在训练时由上文预测下文(或反过来)
- 单向模型,仅使用单侧序列信息
- 代表:N-gram,ELMO
- 自编码(auto encoding)语言模型
- 在训练时预测序列中任意位置的字符
- 双向模型,吸收上下文信息
- 代表:BERT
4. N-gram语言模型
N-gram语言模型是一种基础的语言模型,用于预测下一个词或字符出现的概率,基于前N-1个词或字符。该模型将文本看作是词或字符的有序序列,并假设第n个词仅与前N-1个词相关。
比如,在一个bigram(2-gram)模型中,每个词的出现只依赖于它前面的一个词。例如,"我吃"之后是"苹果"的概率可以表示为P(苹果|我吃)。
优点:
- 计算简单:只需要统计词频和条件词频。
- 实现容易:不需要复杂的算法。
缺点:
- 稀疏性问题:随着N的增加,模型需要的存储空间急剧增加,而大多数N-gram组合在实际数据中可能并不存在。
- 上下文限制:只能捕捉到N-1个词的上下文信息。
尽管有这些局限性,N-gram模型由于其简单和高效仍然在很多应用场景中被广泛使用,如拼写检查、语音识别和机器翻译等。
如何计算成句概率?
- 用S代表句子,w代表单个字或词
- S = w1w2w3w4w5…wn
- P(S) = P(w1,w2,w3,w4,w5…wn)
- 成句概率 -> 词W1~Wn按顺序出现的概率
- P(w1,w2,w3,…,wn) = P(w1)P(w2|w1)P(w3|w1,w2)…P(wn|w1,…,wn-1)
以字为单位
- P(今天天气不错) = P(今)*P(天|今) *P(天|今天) *P(气|今天天) *P(不|今天天气) *P(错|今天天气不)
以词为单位
- P(今天 天气 不错) = P(今天)*P(天气|今天) *P(不错|今天 天气)
如何计算P(今天)?
- P(今天) = Count(今天) / Count_total 语料总词数
- P(天气|今天) = Count(今天 天气) / Count(今天)
- P(不错|今天 天气) = Count(今天 天气 不错) / Count(今天 天气)
- 二元组:今天 天气 2 gram
- 三元组:今天 天气 不错 3 gram
困难:句子太多了!
- 对任意一门语言,N-gram数量都非常庞大,无法穷举,需要简化
马尔科夫假设
- P(wn|w1,…,wn-1) ≈ P(wn|wn-3,wn-2,wn-1)
- 假设第n个词出现的概率,仅受其前面有限个词影响
- P(今天天气不错) = P(今)*P(天|今) *P(天|今天) *P(气|天天) *P(不|天气) *P(错|气不)
马尔科夫假设的缺陷:
- 影响第n个词的因素可能出现在前面很远的地方
long distance dependency例:我读过关于马尔科夫的生平的书
我看过关于马尔科夫的生平的电影
我听过关于马尔科夫的生平的故事
- 影响第n个词的因素可能出现在其后面
- 影响第n个词的因素可能并不在文中
但是,马尔科夫假设下依然可以得到非常有效的模型
语料:
今天 天气 不错 P(今天) = 3 / 12 = 1/4
明天 天气 不错 P(天气|今天) = 2 / 3
今天 天气 不行 P(不错|今天 天气) = 1 / 2
今天 是 晴天 P(不错|天气) = 2/3
3 gram模型
P(今天 天气 不错) = P(今天)*P(天气|今天) *P(不错|今天 天气) = 1 / 12
2 gram模型
P(今天 天气 不错) = P(今天)*P(天气|今天) *P(不错|天气) = 1 / 9
语料:
今天 天气 不错 P(今天) = 3 / 12 = 1/4
明天 天气 不错 P(天气|今天) = 2 / 3
今天 天气 不行 P(不错|今天 天气) = 1 / 2
今天 是 晴天 P(不错|天气) = 2/3
问题:如何给出语料中没出现过的词或ngram概率?
P(今天 天气 糟糕) = P(今天)*P(天气|今天) *P(糟糕|天气)
- 平滑问题(smoothing)
- 理论上说,任意的词组合成的句子,概率都不应当为零
- 如何给没见过的词或ngram分配概率即为平滑问题
- 也称折扣问题(discounting)
4.1 N-gram语言模型-平滑方法
- 回退(backoff)
当三元组a b c不存在时,退而寻找b c二元组的概率
P(c | a b) = P(c | b) * Bow(ab)
Bow(ab)称为二元组a b的回退概率
回退概率有很多计算方式,甚至可以设定为常数
回退可以迭代进行,如序列 a b c d
P(d | a b c) = P(d | b c) * Bow(abc)
P(d | bc) = P(d | c) * Bow(bc)
P(d | c ) = P(d) * Bow©
P(word)不存在如何处理
加1平滑 add-one smooth
对于1gram概率P(word) = Count(word)+1/Count(total_word)+V
V为词表大小
对于高阶概率同样可以
将低频词替换为
预测中遇到的未见过的词,也用代替
一语成谶 -> 一语成
P(|一 语 成)
这是一种nlp处理未登录词(OOV)的常见方法
插值
受到回退平滑的启发,在计算高阶ngram概率是同时考虑低阶的ngram概率值,以插值给出最终结果
实践证明,这种方式效果有提升
λ 可以在验证集上调参确定
4.2 ngram代码
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("e f g b d"))
4.3 语言模型的评价指标
- 困惑度 perplexity
- PPL值与成句概率成反比
一般使用合理的目标文本来计算PPL,若PPL值低,则说明成句概率高,也就说明由此语言模型来判断,该句子的合理性高,这样是一个好的语言模型
- 另一种PPL,用对数求和代替小数乘积
- 本质是相同的,与成句概率呈反比
- 思考:PPL越小,语言模型效果越好,这一结论是否正确?
- 成句概率是个相对值!
4.4 两类语言模型的对比
5. 神经网络语言模型
- Bengio et al. 2003
- 与ngram模型相似使用前n个词预测下一个词
- 输出在字表上的概率分布
- 得到了词向量这一副产品
- 随着相关研究的发展,隐含层模型结构的复杂度不断提升
- DNN -> CNN/RNN -> LSTM/GRU -> transformer
- Devlin et al. 2018 BERT 诞生
- 主要特点:不再使用预测下一个字的方式训练语言模型,转而预测文本中被随机遮盖的某个字
- 这种方式被称为MLM(masked language model)
- 实际上这种方式被提出的时间非常早,并非bert原创
代码
#coding:utf8import torch
import torch.nn as nn
import numpy as np
import math
import random
import os
import re
import matplotlib.pyplot as plt"""
基于pytorch的rnn语言模型
"""class LanguageModel(nn.Module):def __init__(self, input_dim, vocab):super(LanguageModel, self).__init__()self.embedding = nn.Embedding(len(vocab) + 1, input_dim)self.layer = nn.RNN(input_dim, input_dim, num_layers=2, batch_first=True)self.classify = nn.Linear(input_dim, len(vocab) + 1)self.dropout = nn.Dropout(0.1)self.loss = nn.functional.cross_entropy#当输入真实标签,返回loss值;无真实标签,返回预测值def forward(self, x, y=None):x = self.embedding(x) #output shape:(batch_size, sen_len, input_dim)x, _ = self.layer(x) #output shape:(batch_size, sen_len, input_dim)x = x[:, -1, :] #output shape:(batch_size, input_dim)x = self.dropout(x)y_pred = self.classify(x) #output shape:(batch_size, input_dim)if y is not None:return self.loss(y_pred, y)else:return torch.softmax(y_pred, dim=-1)#读取语料获得字符集
#输出一份
def build_vocab_from_corpus(path):vocab = set()with open(path, encoding="utf8") as f:for index, char in enumerate(f.read()):vocab.add(char)vocab.add("<UNK>") #增加一个unk token用来处理未登录词writer = open("vocab.txt", "w", encoding="utf8")for char in sorted(vocab):writer.write(char + "\n")return vocab#加载字表
def build_vocab(vocab_path):vocab = {}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 vocab#加载语料
def load_corpus(path):return open(path, encoding="utf8").read()#随机生成一个样本
#从文本中截取随机窗口,前n个字作为输入,最后一个字作为输出
def build_sample(vocab, window_size, corpus):start = random.randint(0, len(corpus) - 1 - window_size)end = start + window_sizewindow = corpus[start:end]target = corpus[end]# print(window, target)x = [vocab.get(word, vocab["<UNK>"]) for word in window] #将字转换成序号y = vocab[target]return x, y#建立数据集
#sample_length 输入需要的样本数量。需要多少生成多少
#vocab 词表
#window_size 样本长度
#corpus 语料字符串
def build_dataset(sample_length, vocab, window_size, corpus):dataset_x = []dataset_y = []for i in range(sample_length):x, y = build_sample(vocab, window_size, corpus)dataset_x.append(x)dataset_y.append(y)return torch.LongTensor(dataset_x), torch.LongTensor(dataset_y)#建立模型
def build_model(vocab, char_dim):model = LanguageModel(char_dim, vocab)return model#计算文本ppl
def calc_perplexity(sentence, model, vocab, window_size):prob = 0model.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)))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("vocab.txt") #建立字表corpus = load_corpus(corpus_path) #加载语料model = build_model(vocab, char_dim) #建立模型if torch.cuda.is_available():model = model.cuda()optim = torch.optim.Adam(model.parameters(), lr=0.001) #建立优化器for epoch in range(epoch_num):model.train()watch_loss = []for batch in range(int(train_sample / batch_size)):x, y = build_dataset(batch_size, vocab, window_size, corpus) #构建一组训练样本if torch.cuda.is_available():x, y = x.cuda(), y.cuda()optim.zero_grad() #梯度归零loss = model(x, y) #计算losswatch_loss.append(loss.item())loss.backward() #计算梯度optim.step() #更新权重print("=========\n第%d轮平均loss:%f" % (epoch + 1, np.mean(watch_loss)))if not save_weight:returnelse:base_name = os.path.basename(corpus_path).replace("txt", "pth")model_path = os.path.join("model", base_name)torch.save(model.state_dict(), model_path)return#训练corpus文件夹下的所有语料,根据文件名将训练后的模型放到莫得了文件夹
def train_all():for path in os.listdir("corpus"):corpus_path = os.path.join("corpus", path)train(corpus_path)if __name__ == "__main__":# build_vocab_from_corpus("corpus/all.txt")# train("corpus.txt", True)train_all()
6. 语言模型的应用
6.1 语言模型的应用-话者分离
- 根据说话内容判断说话人
- 常用于语言识别系统中,判断录音对话中角色
- 如客服对话录音,判断坐席或客户
- 根据不同腔调判断说话人
- 翻译腔: 这倒霉的房子里竟然有蟑螂,你可以想象到吗?这真是太可怕了!
- 港台腔:你这个人怎么可以这个样子
- 东北味: 我不稀得说你那些事儿就拉倒了
- 本质上为文本分类任务
- 对于每个类别,使用类别语料训练语言模型
- 对于一个新输入的文本,用所有语言模型计算成句概率
- 选取概率最高的类别为预测类别
- 相比一般文本分类模型,如贝叶斯,rf,神经网络等
- 优势:
- 每个类别模型互相独立,样本不均衡或样本有错误对其他模型没有影响
- 可以随时增加新的类别,而不影响旧的类别的效果
- 效果上讲:一般不会有显著优势
- 效率上讲:一般会低于统一的分类模型
6.2 语言模型的应用-文本纠错
- 纠正文本中的错误
- 如:
- 我今天去了天暗门看人民英雄记念碑
- 我今天去了天安门看人民英雄纪念碑
- 错误可能是同音字或形近字等
- 对每一个字建立一个混淆字集合
- 计算整句话成句概率
- 用混淆字集合中的词替代原句中的字,重新计算概率
- 选取得分最高的一个候选句子,如果这个句子比原句的得分增长超过一定的阈值
- 对下一个字重复步骤3-4,直到句子末尾
这种方式有一些缺陷:
- 无法解决多字少字问题
- 阈值的设置非常难把握,如果设置过大,达不到纠错效果;如果设置过小,造成大量替换,有可能改变句子的原意
- 混淆字字表难以完备
- 语言模型的领域性会影响修改结果
- 连续的错字会大幅提升纠错难度
- 一般工业做法:
- 限定一个修改白名单,只判断特定的字词是否要修改
- 如限定只对所有发音为shang wu的片段,计算是否修改为“商务”,其余一概不做处理
- 对于深度学习模型而言,错别字是可以容忍的,所以纠错本身的重要性在下降,一般只针对展示类任务
6.3 语言模型的应用-数字归一化
- 将一个文本中的数字部分转化成对读者友好的样式
- 常见于语言识别系统后,展示文本时使用
- 如:
- 秦皇岛港煤炭库存量在十一月初突然激增,从四百五十四点九万吨增加到七百七十三点四万吨,打破了一九九九年以来的记录
- 秦皇岛港煤炭库存量在11月初突然激增,从454.9万吨增加到773.4万吨,打破了1999年以来的记录
- 找到数字形式符合规范的文本作为原始语料
- 用正则表达式找到数字部分(任意形式)
- 将数字部分依照其格式替换为<阿拉伯数字><汉字数字><汉字连读>等token
- 使用带token文本训练语言模型
- 对于新输入的文本,同样使用正则表达式找到数字部分,之后分别带入各个token,使用语言模型计算概率
- 选取概率最高的token最为最终数字格式,按照规则转化后填入原文本
6.4 语言模型的应用-文本打标
- 本质为序列标注任务
- 可以依照类似方式,处理分词、文本加标点、文本段落切分等任务
- 分词或切分段落只需要一种token;打标点时,可以用多种分隔token,代表不同标点
7. 总结
- 语言模型的核心能力是计算成句概率,依赖这一能力,可以完成大量不同类型的NLP任务。
- 基于统计的语言模型和基于神经网络的语言模型各有使用的场景,大体上讲,基于统计的模型优势在于解码速度,而神经网络的模型通常效果更好。
- 单纯通过PPL评价语言模型是有局限的,通过下游任务效果进行整体评价更好。
- 深入的理解一种算法,有助于发现更多的应用方式。
- 看似简单(甚至错误)的假设,也能带来有意义的结果,事实上,这是简化问题的常见方式。
相关文章:

语言模型(language model)
文章目录 引言1. 什么是语言模型2. 语言模型的主要用途2.1 言模型-语音识别2.2 语言模型-手写识别2.3 语言模型-输入法 3. 语言模型的分类4. N-gram语言模型4.1 N-gram语言模型-平滑方法4.2 ngram代码4.3 语言模型的评价指标4.4 两类语言模型的对比 5. 神经网络语言模型6. 语言…...

【3.Vue子组件调用父组件方法】
1.概述 使用组件建抛出事件的方式来调用父组件的方法,不直接用this.$parent.function的方法,当然这种方式是可以的。 2.代码实现 2.1 父组件代码 父组件写一个方法给子组件调用 // 设备点击事件// equipId:设备id// leftValue:left值// topValue:top…...

算法系列-876-求链表的中间节点
求链表中间节点,如果有两个中间节点取后面那个 链表定义 // lc codestart /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(…...

h5 ws 客户端 监听ws服务器广播的信息
<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>AI智能写作</title><!-- Bootstrap CSS --><meta charset"utf-8"><meta name"viewport" content"widt…...

网络基础之重中之重
目录 IP协议 编辑 基本概念: 协议头格式: 编辑 网段划分 DHCP : CIDR: 特殊的IP地址: IP地址的数量限制: 私有IP和公网IP 路由 路由的过程: 数据链路层 认识以太网&#x…...

HarmonyOS应用开发者-----基础认证试题及答案
HarmonyOS应用开发者基础认证试题及答案 试题会不定时刷新,本试题仅供大家学习参考 【判断题】 2.5/2.5 所有使用@Component修饰的自定义组件都支持onPageShow,onBackPress和onPageHide生命周期函数。 正确(True)错误(False) 回答正确【判断题】 2.5/2.5 在Column和Row容器组…...

C++:string并非以0作为结束符,c_str和data的返回却包含结束符0
C语言中使用char数组保存字符串时,是以字符为0或者\0作为字符串的结束符标志的。 所以一个char str[10]的数组只能合法的保存9个字符(因为最后还要加一个结束符)。 #include <cstring> #include <iostream>using namespace std;int main() {char str[10] ="…...

ChatGPT插件的优缺点
虽然西弗吉尼亚大学的研究人员看到了最新的官方ChatGPT插件——名为“代码解释器”( Code Interpreter)的教育应用潜力,但他们也发现,对于使用计算方法处理针对癌症和遗传疾病的定向治疗的生物数据的科学家来说,这款插…...

北京985学校,交叉学科考英一数三408
北京师范大学(B) 考研难度(☆☆☆) 内容:23考情概况(拟录取和复试分析)、院校概况、23专业目录、23复试详情、各专业考情分析、各科目考情分析。 正文1096字,预计阅读:3分钟 2023考情概况 北…...

ChatGPT 总结前端HTML, JS, Echarts都包含哪些内容
AIGC ChatGPT ,BI商业智能, 可视化Tableau, PowerBI, FineReport, 数据库Mysql Oracle, Office, Python ,ETL Excel 2021 实操,函数,图表,大屏可视化 案例实战 http://t.csdn.cn/zBytu...

企业架构LNMP学习笔记1
项目开发流程: 公司老板或者产品经理,根据市场调查,决定开发一整套互联网产品。 互动社交电商用户论坛(BBS) 产品决策 (老板产品UI设计) 业务实施、代码开发 程序开发人员 前端开发&#x…...

【位运算】leetcode371:两整数之和
一.题目描述 两整数之和 二.思路分析 题目要求我们实现两整数相加,但是不能使用加号,应该立马想到是用位运算来解决问题。之前说过,异或就是“无进位相加”,故本题可以先将两数异或,然后想办法让得到的结果进位即可。…...

【爬虫小知识】如何利用爬虫爬网页——python爬虫
前言 网络时代的到来,给我们提供了海量的信息资源,但是,想要获取这些信息,手动一个一个网页进行查找,无疑是一项繁琐且效率低下的工作。这时,爬虫技术的出现,为我们提供了一种高效的方式去获取…...

什么是跨域问题 ?Spring MVC 如何解决跨域问题 ?Spring Boot 如何解决跨域问题 ?
目录 1. 什么是跨域问题 ? 2. Spring MVC 如何解决跨域问题 ? 3. Spring Boot 如何解决跨域问题 ? 1. 什么是跨域问题 ? 跨域问题指的是不同站点之间,使用 ajax 无法相互调用的问题。 跨域问题的 3 种情况&#x…...

线性代数的学习和整理17:向量空间的基,自然基,基变换等(未完成)
目录 3 向量空间的基:矩阵的基础/轴 3.1 从颜色RGB说起 3.2 附属知识 3.3 什么样的向量可以做基? 3.4 基的分类 3.1.1 不同空间的基---向量组的数量可能不同 3.1.2 自然基 3.1.3 正交基 3.1.4 标准正交基 3.1.5 基和向量/矩阵 3.1.6 基变换 …...

Java中支持分库分表的框架/组件/中间件简介
文章目录 1 sharding-jdbc2 TSharding3 Atlas4 Cobar5 MyCAT6 TDDL7 Vitess 列举一些比较常见的,简单介绍一下: sharding-jdbc(当当) TSharding(蘑菇街) Atlas(奇虎360) Cobar&#…...

7.2 项目2 学生通讯录管理:文本文件增删改查(C 版本)(自顶向下设计+断点调试) (A)
C自学精简教程 目录(必读) 该作业是 作业 学生通讯录管理:文本文件增删改查(C版本) 的C 语言版本。 具体的作业题目描述,要求,可以参考 学生通讯录管理:文本文件增删改查(C版本)。…...

excel怎么设置任意选一个单元格纵横竖横都有颜色
有时excel表格内容过多的时候,我们通过excel设置任意选一个单元格纵横,竖横背景颜色,这样会更加具有辨识度。设置方式截图如下 设置成功后,预览的效果图...

期货-股票交易规则
交易时间 港股:9:00~9:20 集合竞价,9:3012:00,13:0016:00 持续交易,16:00~16:10 随机收市竞价沪股:9:00~9:25 集合竞价,9:3011:30,13:0015:00 持续交易,11:30~12:00 交易申报深股&a…...

Makefile一些语法
ifneq($(filter true,$(xxx)), )的含义 filter 是过滤的意思,它的原型是:$(filter PATTERN…,TEXT), 意义为:过滤掉字串“TEXT”中所有不符合模式“PATTERN”的单词,保留所有符合此模式的单词做返回值。 结合前面的if…...

0基础可以转行编程行业么
在2022年分行业门类分岗位就业人员年平均工资中,信息传输、软件和信息技术服务业的薪资遥遥领先其他行业,为全国平均薪资水平的 1.78 倍,远超第二名金融行业,其年增长率在9.4%,并成为年收入首个过20 万门槛的行业&…...

【spark】dataframe慎用limit
官方:limit通常和order by一起使用,保证结果是确定的 limit 会有两个步骤: LocalLimit ,发生在每个partitionGlobalLimit,发生shuffle,聚合到一个parttion 当提取的n大时,第二步是比较耗时的…...

基于OpenCV+LPR模型端对端智能车牌识别——深度学习和目标检测算法应用(含Python+Andriod全部工程源码)+CCPD数据集
目录 前言总体设计系统整体结构图系统流程图 运行环境Python 环境OpenCV环境Android环境1. 开发软件和开发包2. JDK设置3. NDK设置 模块实现1. 数据预处理2. 模型训练1)训练级联分类器2)训练无分割车牌字符识别模型 3. APP构建1)导入OpenCV库…...

C++学习6
C学习6 基础知识std::thread 实战boost domain socket server 基础知识 std::thread std::thread是C11标准库中的一个类,用于创建并发执行的线程。它的详细用法如下: 头文件 #include <thread>创建线程 std::thread t(func, args...);其中&am…...

bazel使用中存在的问题
只开远端缓存时。kernel采用的bazel编译,遇到如下问题: 1、Action 详情二进制文件解析为文本文件时报错,无法进一步比较分析导致缓存不命中的原因。--- JDK版本的问题 2、远端缓存全部命中时间收益不明显 ---需分析是否为网络原因 3、$HOM…...

svn软连接和文件忽略
软连接 1)TortoiseSVN->Properties->New->Externals->New 2)填入软连接信息 Local path: 写下软连接后的文件夹的名字 URL: 想要软连接的牡蛎->TortoiseSVN->Repo-browser 复制下填入 文件忽略 以空格隔开就行...

自动驾驶攻城战,华为小鹏先亮剑
点击关注 文|刘俊宏 编|苏扬、王一粟 本文为光锥智能x腾讯科技联合出品 2023年过半,城市NOA(城市领航辅助驾驶)的元年如预期中到来了吗? 8月25日,成都车展开幕,与4个月之前的上海…...

企业供应链数字化怎么做?企业数字化供应链流程落地方式
什么是供应链?简单来说,供应链是围绕客户需求,以提高产品流通各个环节的效率为目标,通过资源整合的方式来实现产品从设计、生产到销售、服务整个环节的组织形态。如同人工智能、区块链、5G等技术的发展带来的各种行业变化…...

java八股文面试[多线程]——synchronized 和lock的区别
其他差别: synchronized是隐式的加锁,lock是显式的加锁; synchronized底层采用的是objectMonitor,lock采用的AQS; synchronized在进行加锁解锁时,只有一个同步队列和一个等待队列, lock有一个同步队列,可以有多个等待队列; synchronized使用了object类的wait和noti…...

实现一个简单的控制台版用户登陆程序, 程序启动提示用户输入用户名密码. 如果用户名密码出错, 使用自定义异常的方式来处理
//密码错误异常类 public class PasswordError extends Exception {public PasswordError(String message){super(message);} }//用户名错误异常类 public class UserError extends Exception{public UserError(String message){super(message);} }import java.util.Scanner;pu…...