【ChatGPT前世今生】前置知识Seq2Seq入门理解

【ChatGPT前世今生】前置知识Seq2Seq入门理解

    • 1、环境准备与依赖包安装
    • 2、数据集准备
    • 3、数据集预处理与读取
    • 4、定义Seq2Seq模型的基础类
    • 5、预处理训练数据集
    • 6、定义训练过程
    • 7、定义验证过程
    • 8、执行训练与验证过程
    • 9、展示模型的结果,进行进一步分析

最近一段时间,ChatGPT非常热门,但是,要理解ChatGPT的工作原理,得追溯至Transformer、Seq2Seq、Word2Vec这些早期的自然语言处理研究成果,本文主要回顾Seq2Seq
Seq2Seq,其英文原称就是Sequence to Sequence,翻译过来就是“序列到序列”,其文献可以追溯至发表在NIPS 2014的《Sequence to Sequence Learning with Neural Networks》,该文章的谷歌学术引用已经多于2.1万次,可见其在NLP领域的重要性,此后近9年的研究工作,可以说都或多或少受到了该论文思维的影响。

在这里插入图片描述

我们现在回过头来看,其实Seq2Seq的思想真的很直观,就是把语言生成任务建模为序列到序列的任务,输入是一个序列,输出也是一个序列。其在提出之初,主要是用于翻译任务,后来广泛用到对话生成、摘要生成等文本生成任务当中。这种结构的显著特点是:输入序列和输出序列的长度是可变的,且没有直接的一一对应的关系,如上图所示。

下面将以翻译任务,简单介绍Seq2Seq的工作原理。

1、环境准备与依赖包安装

参考博客:

  • 【Python学习】纯终端命令开始你的Anaconda安装与Python环境管理
  • 【Python学习】Windows10开始你的Anaconda安装与Python环境管理
  • 【Python编程】服务器长期开启jupyter notebook远程连接服务
  • Pytorch安装指南

在conda创建的python环境当中安装pytorch以及wget:

conda install pytorch torchvision torchaudio cpuonly -c pytorch
pip install wget

导入re、torch等依赖包

%matplotlib inline
from __future__ import unicode_literals, print_function, division
from io import open
import unicodedata
import string
import re
import randomimport torch
import torch.nn as nn
from torch import optim
import torch.nn.functional as Fdevice = torch.device("cuda" if torch.cuda.is_available() else "cpu")
/home/phd-chen.yirong/anaconda3/envs/py38_llm/lib/python3.8/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.htmlfrom .autonotebook import tqdm as notebook_tqdm

2、数据集准备

通过以下链接下载数据集并且解压到与本文件相同的路径

https://download.pytorch.org/tutorial/data.zip

# 下载数据集文件
import wget
data_url = "https://download.pytorch.org/tutorial/data.zip"
wget.download(data_url, "./data.zip")
100% [..........................................................................] 2882130 / 2882130'./data (1).zip'

解压数据文件:

# 解压数据集文件
import zipfiledef unzip_file(zip_src, dst_dir):# zip_src源文件夹# dst_dir目标文件夹r = zipfile.is_zipfile(zip_src)if r:     fz = zipfile.ZipFile(zip_src, 'r')for file in fz.namelist():fz.extract(file, dst_dir)       else:print('This is not zip')zip_data_path = "./data.zip"  # 在这里修改需要解压的文件夹
unzip_file(zip_src=zip_data_path, dst_dir="./")

3、数据集预处理与读取

众所周知,NLP任务是需要有一个词表的,我们需要将句子转换为词序列,再将词序列映射为向量,然后用这个词向量进行各种任务运算,词向量的工作原理会在另一篇博客展开讨论。我们现在需要知道的是:

  • 1、给定一个语料库(指由若干个句子序列组成的数据集,可以是翻译数据集,可以是对话数据集等等),我们首先要基于该数据集进行分词,然后进行词频统计,得到一个词表(词及其编号),如果是翻译任务,则有两个不同的词表分别对应待翻译语言以及翻译后的语言,通常如下所示:
SOS: 0
EOS: 1
a: 2
...

这个词表,实际上就是我们在执行NLP任务时的搜索空间,每执行一步生成,实际上就是在词表当中检索最可能生成的一个词。特别地,词表可能很大,通常会由几万个单词组成,因此其对应的分类器也会非常大,每次需要从数万个单词当中挑出最可能的一个或若干个单词作为输出。

  • 2、然后,针对每一个句子,需要先根据词表把其转换为由编号组成的序列,类似于[0, 8, 20, 100, ..., 1]的形式,然后再根据编号获得每个词对应的向量表示,将向量序列输入到Seq2Seq模型当中,进行模型的运算推理,并返回推理后的结果,例如某一步推理得到的预测向量,根据这个向量检索最接近的词向量,用该词向量对应的单词作为输出。

以下代码为词表类的实现代码,其中类的成员word2index、index2word分别可以通过单词查询对应的编号,以及通过编号查询对应的单词,那怕是ChatGPT,实际上也是需要进行这两步的。

SOS_token = 0
EOS_token = 1class Lang:def __init__(self, name):self.name = nameself.word2index = {}self.word2count = {}self.index2word = {0: "SOS", 1: "EOS"}self.n_words = 2  # Count SOS and EOSdef addSentence(self, sentence):for word in sentence.split(' '):self.addWord(word)def addWord(self, word):if word not in self.word2index:self.word2index[word] = self.n_wordsself.word2count[word] = 1self.index2word[self.n_words] = wordself.n_words += 1else:self.word2count[word] += 1

以下过程是一些正则化处理过程,实际上就是进行数据清洗,简化任务

# Turn a Unicode string to plain ASCII, thanks to
# https://stackoverflow.com/a/518232/2809427
def unicodeToAscii(s):return ''.join(c for c in unicodedata.normalize('NFD', s)if unicodedata.category(c) != 'Mn')# Lowercase, trim, and remove non-letter charactersdef normalizeString(s):s = unicodeToAscii(s.lower().strip())s = re.sub(r"([.!?])", r" \1", s)s = re.sub(r"[^a-zA-Z.!?]+", r" ", s)return s

通过readLangs函数实现词表的构建,其包括:读入语料库/数据集,分词,更新词表。

def readLangs(lang1, lang2, reverse=False):print("Reading lines...")# Read the file and split into lineslines = open('data/%s-%s.txt' % (lang1, lang2), encoding='utf-8').\read().strip().split('\n')# Split every line into pairs and normalizepairs = [[normalizeString(s) for s in l.split('\t')] for l in lines]# Reverse pairs, make Lang instancesif reverse:pairs = [list(reversed(p)) for p in pairs]input_lang = Lang(lang2)output_lang = Lang(lang1)else:input_lang = Lang(lang1)output_lang = Lang(lang2)return input_lang, output_lang, pairs
MAX_LENGTH = 10eng_prefixes = ("i am ", "i m ","he is", "he s ","she is", "she s ","you are", "you re ","we are", "we re ","they are", "they re "
)def filterPair(p):return len(p[0].split(' ')) < MAX_LENGTH and \len(p[1].split(' ')) < MAX_LENGTH and \p[1].startswith(eng_prefixes)def filterPairs(pairs):return [pair for pair in pairs if filterPair(pair)]
def prepareData(lang1, lang2, reverse=False):input_lang, output_lang, pairs = readLangs(lang1, lang2, reverse)print("Read %s sentence pairs" % len(pairs))pairs = filterPairs(pairs)print("Trimmed to %s sentence pairs" % len(pairs))print("Counting words...")for pair in pairs:input_lang.addSentence(pair[0])output_lang.addSentence(pair[1])print("Counted words:")print(input_lang.name, input_lang.n_words)print(output_lang.name, output_lang.n_words)return input_lang, output_lang, pairsinput_lang, output_lang, pairs = prepareData('eng', 'fra', True)
print(random.choice(pairs))
Reading lines...
Read 135842 sentence pairs
Trimmed to 10599 sentence pairs
Counting words...
Counted words:
fra 4345
eng 2803
['je suis musicienne .', 'i m a musician .']

4、定义Seq2Seq模型的基础类

广义来说,一切序列到序列的任务,都可以通过模型Seq2Seq来实现,但是具体到最初的模型,Seq2Seq的具体实现是基于RNN算法/模型的。
更通俗一点,Seq2Seq框架通常包含:处理输入序列的模块(通常称为编码器,Encoder),生成输出序列的模块(通常称为解码器,Decoder)。
我们在这里不赘述RNN算法的具体计算步骤,感兴趣的同学可以百度一下。下面的模型的实现主要采用了RNN的一种变体:GRU,但它仍然属于RNN算法的一种。

本文实现的Seq2Seq主要包括:EncoderRNN模块以及AttnDecoderRNN,其中EncoderRNN由词嵌入层(self.embedding)和一层GRU(self.gru)组成;AttnDecoderRNN由词嵌入层(self.embedding)、注意力计算层(self.attn、self.attn_combine)、GRU层(self.gru)以及输出的词分类层(self.out)组成。

本文通过一个可训练的线性层来实现编码器的输出和解码器的输入之间的注意力权重计算,同时也通过另一个可训练的线性层来实现将注意力加权到解码器的输入,得到最终的解码器的输入。这个实际上相当于注意力权重是可以通过训练得到的,解码器最终的输入由编码器的输出、注意力权重,以及对这两部分的加权的数值共同决定。
解码器最终的输入 = [ 编码器的输出 , 注意力权 重 可训练 ] ∗ [ 加权数值矩阵 ] 可训练 解码器最终的输入=[编码器的输出, 注意力权重_{可训练}]*[加权数值矩阵]_{可训练} 解码器最终的输入=[编码器的输出,注意力权可训练][加权数值矩阵]可训练

当然,给输入序列加注意力有很多种实现方式,并不局限于以上方法

# 编码器:处理输入序列
class EncoderRNN(nn.Module):def __init__(self, input_size, hidden_size):super(EncoderRNN, self).__init__()self.hidden_size = hidden_size # 词向量的维度self.embedding = nn.Embedding(input_size, hidden_size) # input_size表示输入序列对应的语言的词表的大小self.gru = nn.GRU(hidden_size, hidden_size)def forward(self, input, hidden):embedded = self.embedding(input).view(1, 1, -1)output = embeddedoutput, hidden = self.gru(output, hidden)return output, hiddendef initHidden(self):return torch.zeros(1, 1, self.hidden_size, device=device)# 解码器:解码获得输出序列
class DecoderRNN(nn.Module):def __init__(self, hidden_size, output_size):super(DecoderRNN, self).__init__()self.hidden_size = hidden_size # 词向量的维度self.embedding = nn.Embedding(output_size, hidden_size) # output_size表示输出序列对应的语言的词表的大小self.gru = nn.GRU(hidden_size, hidden_size)self.out = nn.Linear(hidden_size, output_size)self.softmax = nn.LogSoftmax(dim=1)def forward(self, input, hidden):output = self.embedding(input).view(1, 1, -1)output = F.relu(output)output, hidden = self.gru(output, hidden)output = self.softmax(self.out(output[0]))return output, hiddendef initHidden(self):return torch.zeros(1, 1, self.hidden_size, device=device)# 加注意力的解码器
class AttnDecoderRNN(nn.Module):def __init__(self, hidden_size, output_size, dropout_p=0.1, max_length=MAX_LENGTH):super(AttnDecoderRNN, self).__init__()self.hidden_size = hidden_sizeself.output_size = output_sizeself.dropout_p = dropout_pself.max_length = max_lengthself.embedding = nn.Embedding(self.output_size, self.hidden_size)self.attn = nn.Linear(self.hidden_size * 2, self.max_length)self.attn_combine = nn.Linear(self.hidden_size * 2, self.hidden_size)self.dropout = nn.Dropout(self.dropout_p)self.gru = nn.GRU(self.hidden_size, self.hidden_size)self.out = nn.Linear(self.hidden_size, self.output_size)def forward(self, input, hidden, encoder_outputs):embedded = self.embedding(input).view(1, 1, -1)embedded = self.dropout(embedded)attn_weights = F.softmax(self.attn(torch.cat((embedded[0], hidden[0]), 1)), dim=1)attn_applied = torch.bmm(attn_weights.unsqueeze(0),encoder_outputs.unsqueeze(0))output = torch.cat((embedded[0], attn_applied[0]), 1)output = self.attn_combine(output).unsqueeze(0)output = F.relu(output)output, hidden = self.gru(output, hidden)output = F.log_softmax(self.out(output[0]), dim=1)return output, hidden, attn_weightsdef initHidden(self):return torch.zeros(1, 1, self.hidden_size, device=device)

5、预处理训练数据集

定义原始输入文本的处理函数,将句子(字符串)转换为模型可以理解的数字序列(张量)。

def indexesFromSentence(lang, sentence):return [lang.word2index[word] for word in sentence.split(' ')]def tensorFromSentence(lang, sentence):indexes = indexesFromSentence(lang, sentence)indexes.append(EOS_token)return torch.tensor(indexes, dtype=torch.long, device=device).view(-1, 1)def tensorsFromPair(pair):input_tensor = tensorFromSentence(input_lang, pair[0])target_tensor = tensorFromSentence(output_lang, pair[1])return (input_tensor, target_tensor)

6、定义训练过程

一个神经网络模型的训练过程,实际上就是:

  • 不断读取数据样本,将数据样本转换为模型所需要的输入格式;
  • 步骤1:模型根据输入的样本计算输出值;
  • 步骤2:调用损失函数(某种计算距离的公式,例如标准差)计算模型输出值和真实值的差距(俗称损失值,loss);
  • 步骤3:利用损失值驱动优化算法(优化器)去对模型的所有参数进行更新,重复以上步骤若干次。

总的来说,每一步训练过程需要:样本(模型的输入和参考答案)、模型、优化器、损失函数。

经过训练,模型的参数会不断更新,最终得到一个训练后的模型,这就是神经网络模型的训练过程。更加具体而言,其中的损失函数、优化器又会有很多具体的实现,下面使用的损失函数是通过criterion参数传入的,模型分为编码器和解码器两部分,分别通过encoder、decoder传入,编码器和解码器的优化器通过encoder_optimizer、decoder_optimizer传入。

teacher_forcing_ratio = 0.5def train(input_tensor, target_tensor, encoder, decoder, encoder_optimizer, decoder_optimizer, criterion, max_length=MAX_LENGTH):encoder_hidden = encoder.initHidden()encoder_optimizer.zero_grad()decoder_optimizer.zero_grad()input_length = input_tensor.size(0)target_length = target_tensor.size(0)encoder_outputs = torch.zeros(max_length, encoder.hidden_size, device=device)loss = 0for ei in range(input_length):encoder_output, encoder_hidden = encoder(input_tensor[ei], encoder_hidden)encoder_outputs[ei] = encoder_output[0, 0]decoder_input = torch.tensor([[SOS_token]], device=device)decoder_hidden = encoder_hiddenuse_teacher_forcing = True if random.random() < teacher_forcing_ratio else Falseif use_teacher_forcing:# Teacher forcing: Feed the target as the next inputfor di in range(target_length):decoder_output, decoder_hidden, decoder_attention = decoder(decoder_input, decoder_hidden, encoder_outputs)loss += criterion(decoder_output, target_tensor[di])decoder_input = target_tensor[di]  # Teacher forcingelse:# Without teacher forcing: use its own predictions as the next inputfor di in range(target_length):decoder_output, decoder_hidden, decoder_attention = decoder(decoder_input, decoder_hidden, encoder_outputs)topv, topi = decoder_output.topk(1)decoder_input = topi.squeeze().detach()  # detach from history as inputloss += criterion(decoder_output, target_tensor[di])if decoder_input.item() == EOS_token:breakloss.backward()encoder_optimizer.step()decoder_optimizer.step()return loss.item() / target_length

训练过程的辅助函数:

import time
import mathdef asMinutes(s):m = math.floor(s / 60)s -= m * 60return '%dm %ds' % (m, s)def timeSince(since, percent):now = time.time()s = now - sincees = s / (percent)rs = es - sreturn '%s (- %s)' % (asMinutes(s), asMinutes(rs))

定义训练过程的显示函数:

def trainIters(encoder, decoder, n_iters, print_every=1000, plot_every=100, learning_rate=0.01):start = time.time()plot_losses = []print_loss_total = 0  # Reset every print_everyplot_loss_total = 0  # Reset every plot_everyencoder_optimizer = optim.SGD(encoder.parameters(), lr=learning_rate) # 优化器,通常指定待优化的参数以及学习率模式decoder_optimizer = optim.SGD(decoder.parameters(), lr=learning_rate) # 优化器,通常指定待优化的参数以及学习率模式training_pairs = [tensorsFromPair(random.choice(pairs))for i in range(n_iters)]criterion = nn.NLLLoss() # 损失函数,用于计算模型输出和真实答案之间的差值for iter in range(1, n_iters + 1):'''执行训练过程,n_iters:表示训练步数'''training_pair = training_pairs[iter - 1]input_tensor = training_pair[0]target_tensor = training_pair[1]# 执行train函数,进行训练并且返回损失值loss = train(input_tensor, target_tensor, encoder,decoder, encoder_optimizer, decoder_optimizer, criterion)print_loss_total += lossplot_loss_total += lossif iter % print_every == 0:print_loss_avg = print_loss_total / print_everyprint_loss_total = 0print('%s (%d %d%%) %.4f' % (timeSince(start, iter / n_iters),iter, iter / n_iters * 100, print_loss_avg))if iter % plot_every == 0:plot_loss_avg = plot_loss_total / plot_everyplot_losses.append(plot_loss_avg)plot_loss_total = 0showPlot(plot_losses)
import matplotlib.pyplot as plt
plt.switch_backend('agg')
import matplotlib.ticker as ticker
import numpy as npdef showPlot(points):plt.figure()fig, ax = plt.subplots()# this locator puts ticks at regular intervalsloc = ticker.MultipleLocator(base=0.2)ax.yaxis.set_major_locator(loc)plt.plot(points)

7、定义验证过程

def evaluate(encoder, decoder, sentence, max_length=MAX_LENGTH):with torch.no_grad():input_tensor = tensorFromSentence(input_lang, sentence)input_length = input_tensor.size()[0]encoder_hidden = encoder.initHidden()encoder_outputs = torch.zeros(max_length, encoder.hidden_size, device=device)for ei in range(input_length):encoder_output, encoder_hidden = encoder(input_tensor[ei],encoder_hidden)encoder_outputs[ei] += encoder_output[0, 0]decoder_input = torch.tensor([[SOS_token]], device=device)  # SOSdecoder_hidden = encoder_hiddendecoded_words = []decoder_attentions = torch.zeros(max_length, max_length)for di in range(max_length):decoder_output, decoder_hidden, decoder_attention = decoder(decoder_input, decoder_hidden, encoder_outputs)decoder_attentions[di] = decoder_attention.datatopv, topi = decoder_output.data.topk(1)if topi.item() == EOS_token:decoded_words.append('<EOS>')breakelse:decoded_words.append(output_lang.index2word[topi.item()])decoder_input = topi.squeeze().detach()return decoded_words, decoder_attentions[:di + 1]
def evaluateRandomly(encoder, decoder, n=10):for i in range(n):pair = random.choice(pairs)print('>', pair[0])print('=', pair[1])output_words, attentions = evaluate(encoder, decoder, pair[0])output_sentence = ' '.join(output_words)print('<', output_sentence)print('')

8、执行训练与验证过程

训练过程实际上就是不停地调整encoder1和attn_decoder1的所有参数,使得模型的每一次输出尽可能拟合标准答案。
这其中涉及到优化算法,打印的是:
训练所需时间,当前所处迭代步数,当前已经执行的步数的百分比,平均损失值

%matplotlib inline
hidden_size = 256
encoder1 = EncoderRNN(input_lang.n_words, hidden_size).to(device)
attn_decoder1 = AttnDecoderRNN(hidden_size, output_lang.n_words, dropout_p=0.1).to(device)trainIters(encoder1, attn_decoder1, 75000, print_every=5000)
1m 34s (- 22m 8s) (5000 6%) 2.8433
3m 7s (- 20m 16s) (10000 13%) 2.2873
4m 39s (- 18m 36s) (15000 20%) 1.9658
6m 13s (- 17m 5s) (20000 26%) 1.7078
7m 46s (- 15m 32s) (25000 33%) 1.5310
9m 20s (- 14m 0s) (30000 40%) 1.3317
10m 54s (- 12m 28s) (35000 46%) 1.2264
12m 29s (- 10m 55s) (40000 53%) 1.1010
14m 3s (- 9m 22s) (45000 60%) 0.9866
15m 39s (- 7m 49s) (50000 66%) 0.8691
17m 14s (- 6m 16s) (55000 73%) 0.7777
18m 48s (- 4m 42s) (60000 80%) 0.7417
20m 22s (- 3m 8s) (65000 86%) 0.6802
21m 55s (- 1m 33s) (70000 93%) 0.6146
23m 29s (- 0m 0s) (75000 100%) 0.5637

在这里插入图片描述

evaluateRandomly(encoder1, attn_decoder1)
> je vais me doucher .
= i m going to take a shower .
< i m getting to get . . <EOS>> vous etes tres intelligent .
= you re very intelligent .
< you re very intelligent . <EOS>> nous sommes ponctuels .
= we re punctual .
< we re punctual . <EOS>> je ne suis pas assez bon pour vous .
= i m not good enough for you .
< i m not good enough for you . . .> je suis reellement fier de toi .
= i m really proud of you .
< i m really proud of you . <EOS>> il ne m a jamais frappe auparavant .
= he s never hit me before .
< he s never not before before . <EOS>> je n en suis pas certain .
= i m not certain .
< i m not certain of it . <EOS>> vous ne cooperez pas .
= you re not cooperating .
< you re not cooperating . <EOS>> tu es etourdi .
= you re forgetful .
< you re forgiven . <EOS>> vous etes fort raffinee .
= you re very sophisticated .
< you re very sophisticated . <EOS>
%matplotlib inline
output_words, attentions = evaluate(encoder1, attn_decoder1, "je suis trop froid .")
plt.matshow(attentions.numpy())

在这里插入图片描述

9、展示模型的结果,进行进一步分析

主要是进行注意力分析,感兴趣的同学可以百度一下什么是注意力,实际上就是展示了模型通过训练,在进行翻译任务时,预测某个词是,对输入的句子的各个单词分配的权重。简单来说,预测某一个位置的词时,对于输入的序列的各个词的注意力(分配的权重),是不一样的。

%matplotlib inline
def showAttention(input_sentence, output_words, attentions):# Set up figure with colorbarfig = plt.figure()ax = fig.add_subplot(111)cax = ax.matshow(attentions.numpy(), cmap='bone')fig.colorbar(cax)# Set up axesax.set_xticklabels([''] + input_sentence.split(' ') +['<EOS>'], rotation=90)ax.set_yticklabels([''] + output_words)# Show label at every tickax.xaxis.set_major_locator(ticker.MultipleLocator(1))ax.yaxis.set_major_locator(ticker.MultipleLocator(1))plt.show()def evaluateAndShowAttention(input_sentence):output_words, attentions = evaluate(encoder1, attn_decoder1, input_sentence)print('input =', input_sentence)print('output =', ' '.join(output_words))showAttention(input_sentence, output_words, attentions)evaluateAndShowAttention("elle a cinq ans de moins que moi .")evaluateAndShowAttention("elle est trop petit .")evaluateAndShowAttention("je ne crains pas de mourir .")evaluateAndShowAttention("c est un jeune directeur plein de talent .")
input = elle a cinq ans de moins que moi .
output = she is five years younger than i am <EOS>

在这里插入图片描述

input = elle est trop petit .
output = she s too short . <EOS>

在这里插入图片描述

input = je ne crains pas de mourir .
output = i m not dying of dying . <EOS>

在这里插入图片描述

input = c est un jeune directeur plein de talent .
output = he s a talented young s . <EOS>

在这里插入图片描述

参考:
https://pytorch.org/tutorials/intermediate/seq2seq_translation_tutorial.html

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

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

相关文章

数据分析 × 人文社科:高校交叉学科教学经验分享

随着新一轮科技革命与产业变革的加速演进&#xff0c;学科间的交叉融合不断升级&#xff0c;由数据驱动的系列交叉学科备受瞩目&#xff0c;然而&#xff0c;在实际教学与学科建设的过程中&#xff0c;对于数据科学引入至相关学科&#xff0c;高校教师还是普遍面临着比较多的问…

华为又招了一名天才少年,他背后的故事堪称传奇!

上一篇&#xff1a;ChatGPT的工作原理&#xff08;纯干货&#xff0c;万字长文&#xff09; 2019年6月&#xff0c;华为创始人任正非发起华为“天才少年”项目&#xff0c;用顶级挑战和顶级薪酬去吸引顶尖人才的项目。并表示&#xff0c;华为将从全世界招进20-30名天才少年&…

华为又招了一名天才少年!

2019年6月&#xff0c;华为创始人任正非发起华为“天才少年”项目&#xff0c;用顶级挑战和顶级薪酬去吸引顶尖人才的项目。并表示&#xff0c;华为将从全世界招进20-30名天才少年&#xff0c;2020年还计划从世界范围招进200-300名天才少年。 这不就在上个月&#xff0c;华为最…

打造人工智能创新之源,共建昇思开源新生态

3月31日&#xff0c;由昇思MindSpore开源社区主办的昇思开源三周年生日会如期举行。本次生日会对即将发布的昇思MindSpore 2.0正式版本进行预告、发布了最新版的昇思大模型平台&#xff0c;同时还发布了昇思大模型技术公开课程。生日会给开发者展示了三年来昇思在人才培养、开源…

如何顺势而为,让ChatGPT为教育所用?

恐惧和回避无法阻挡科技的浪潮&#xff0c;教育与AI的深度融合时代已经到来&#xff0c;如何把AI当做工具&#xff0c;把其成为教育的机会而非威胁&#xff0c;是教育体系未来不得不得面对的新变化。 接受ChatGPT作为一种教学辅助工具&#xff0c;成为教师的朋友或者帮手&…

干货 | 如何才能让ChatGPT帮我做科研?

Hello&#xff0c;大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是喵君姐姐&#xff5e; ChatGPT是OpenAI于2022年11月开发的聊天机器人。ChatGPT由于能够帮助回答许多学术问题而迅速受到学生欢迎。那如何在学习中使用ChatGPT呢&#xff1f; 人工智能技术对未来写作…

ChatGPT:给教育创新带来风险与挑战

在教育界&#xff0c;当前对ChatGPT的关注固然有一部分原因是它所能带来的教育创新&#xff0c;但更多的原因是ChatGPT同时也在冲击着教师的角色定位&#xff0c;推动着人才培养目标的转型&#xff0c;逼迫着学生和教师走出舒适区。况且&#xff0c;ChatGPT还不断诱发教育中的技…

华为最新「天才少年」:博士四年21篇论文,却自称是个「低能儿」

金磊 发自 凹非寺量子位 | 公众号 QbitAI 华为最新“天才少年”&#xff0c;新鲜出炉。 他叫宁博宇&#xff0c;26岁&#xff0c;来自电子科技大学&#xff0c;是通信抗干扰技术国家级重点实验室的2019级博士研究生。 △图源&#xff1a;电子科技大学官方网站 而此次他被华为pi…

华为最新「天才少年」:26岁年薪百万,博士四年21篇论文

来源&#xff1a;量子位 华为最新“天才少年”&#xff0c;新鲜出炉。 他叫宁博宇&#xff0c;26岁&#xff0c;来自电子科技大学&#xff0c;是通信抗干扰技术国家级重点实验室的2019级博士研究生。 △图源&#xff1a;电子科技大学官方网站 而此次他被华为pick后&#xff0c;…

华为最新天才少年曝光!博士四年21篇论文

点击下方卡片&#xff0c;关注“CVer”公众号 AI/CV重磅干货&#xff0c;第一时间送达 点击进入—>【计算机视觉】微信技术交流群 金磊 发自 凹非寺转载自&#xff1a;量子位&#xff08;QbitAI&#xff09; 华为最新“天才少年”&#xff0c;新鲜出炉。 他叫宁博宇&#xf…

Android QQ、微信、Facebook和推特第三方登录

在Android 很多的APP应用中&#xff0c;都需要利用第三方登录来实现APP 自己本身应用的快速登录。这里的第三方平台&#xff0c;一般是已经有大量用户的平台&#xff0c;比如说国内的QQ,微信&#xff0c;国外的Facebook和Twitter 等&#xff0c;而本篇博客主要实现了这四个平台…

把 ChatGPT 加到你自己的程序里,简单到只需要一样东西

那就是&#xff1a; 钱 零基础python入门教程&#xff1a;python666.cn 大家好&#xff0c;欢迎来到 Crossin的编程教室。 这两天 ChatGPT 疯狂刷屏&#xff0c;可能有人都看烦了。也有很多人会有个疑问&#xff0c;这东西跟我有啥关系呢&#xff1f;我甚至连注册都注册不了啊……

ChatGPT 有什么功能?AI技术的发展在国内有啥体现?

最近&#xff0c;ChatGPT逐渐被大家所关注到&#xff0c;其实在去年年底ChatGPT 这个AI聊天机器人问世之后&#xff0c;在国外已经非常火爆。近日&#xff0c;很多小伙伴儿玩儿 ChatGPT 不亦乐乎&#xff0c;无法自拔....,感觉各行各业可能要发生大变化。 1&#xff1a;什么是C…

ChatGPT应用技巧五:如何实现一个垂直领域的AI问答机器人

原文&#xff1a;ChatGPT应用技巧五&#xff1a;如何实现一个垂直领域的AI问答机器人|向量|ai|知识库|上下文|插件功能_网易订阅 “由于ChatGPT的数据更新目前只截止到2021年9月&#xff0c;并且它也不一定有特定垂直领域的数据。如何将这些领域的最新数据“喂”给ChatGPT&…

ChatGPT:开放AI平台的最新进展和功能

第一章&#xff1a;引言 在过去的几年中&#xff0c;人工智能技术取得了长足的发展&#xff0c;其在各个领域的应用也日益广泛。而在AI技术中&#xff0c;自然语言处理&#xff08;NLP&#xff09;一直是备受关注的领域之一。ChatGPT作为OpenAI的开放AI平台上的一项重要技术&am…

对话 ChatGPT:现象级 AI 应用,将如何阐释「研发效能管理」?

ChatGPT 已然是 2023 开年至今&#xff0c;互联网上最热的话题没有之一。从去年的 AI 图片生成&#xff0c;到 ChatGPT&#xff0c;再到现在各种基于大模型的应用如雨后春笋般出现……在人们探讨技术无限可能的同时&#xff0c;另一个更深刻的命题也不可回避地浮现出来&#xf…

朋友圈转发集赞截图生成工具,以假乱真!

今天分享的是2款转发集赞截图生成工具。 我自己是做平台运营的&#xff0c;平时转发、集赞、拼团、秒杀等等乱七八糟活动没少策划过。 但其实对我个人来说还是很讨厌这些东西的&#xff0c;天天求点赞/求转发/求砍一刀&#xff0c;实在是烦人&#xff0c;所以我自己从来都不参与…

mail发邮件

目录 一&#xff1a;导包 二&#xff1a;使用 1&#xff1a;在qq邮箱生成授权码&#xff1a;允许此qq可以被我们的电脑指挥发邮件 2&#xff1a;application.properties进行配置&#xff08;并把授权码放到spring.mail.passwordkytxteybnhhldiie&#xff09; 3&#xff1a;…

chatgpt赋能python:Python如何群发邮件:简介

Python如何群发邮件&#xff1a;简介 Python是一种功能强大的编程语言&#xff0c;它能够在多个方面为您提供帮助。其中之一是自动化邮件和批量邮件发送。如果您需要发送数百封邮件&#xff0c;或者每天都需要发送类似的邮件&#xff0c;使用Python进行自动化发送可能是最好的…

【编程实践】Google Guava 极简教程

前言 Guava 工程包含了若干被 Google 的 Java 项目广泛依赖 的核心库&#xff0c;我们希望通过此文档为 Guava 中最流行和最强大的功能&#xff0c;提供更具可读性和解释性的说明。 适用人群 本教程是基础教程&#xff0c;适合基础Java开发者的进阶学习。 Adding Guava to your…