gitweixin
  • 首页
  • 小程序代码
    • 资讯读书
    • 工具类
    • O2O
    • 地图定位
    • 社交
    • 行业软件
    • 电商类
    • 互联网类
    • 企业类
    • UI控件
  • 大数据开发
    • Hadoop
    • Spark
    • Hbase
    • Elasticsearch
    • Kafka
    • Flink
    • 数据仓库
    • 数据挖掘
    • flume
    • Kafka
    • Hive
    • shardingsphere
    • solr
  • 开发博客
    • Android
    • php
    • python
    • 运维
    • 技术架构
    • 数据库
  • 程序员网赚
  • bug清单
  • 量化投资
  • 在线查询工具
    • 去行号
    • 在线时间戳转换工具
    • 免费图片批量修改尺寸在线工具
    • SVG转JPG在线工具

分类归档人工智能

精品微信小程序开发门户,代码全部亲测可用

  • 首页   /  
  • 分类归档: "人工智能"
  • ( 页面5 )
深度学习 4月 5,2022

Word Embedding的几种模型和示例

介绍

人类有能力理解单词并轻松地从中获取含义。然而,在当今世界,大多数任务都是由计算机执行的。例如,如果您想知道今天是晴天还是下雨天,则必须在 Google 中输入文本查询。现在的问题是,机器将如何频繁地理解和处理文本中呈现的如此大量的信息?答案是词嵌入。

Word Embeddings 基本上是向量(文本转换为数字),用于捕获单词的含义、各种上下文和语义关系。嵌入本质上是使用预定义字典将单词映射到其对应向量。

例如,

句子: It will rain heavily today.

字典:{“it”:[1,0,0,0,0],“will”:[0,1,0,0,0],“rain”:[0,0,1,0,0] , “ heavily ”: [0,0,0,1,0], “today”: [0,0,0,0,1]}

在这里,每个单词都被分配了一个唯一的向量(例如),以便区分所有单词。

Let the corpus comprise three sentences.

S1 = In monsoon, it will rain.

S2 = rain rain come again.

S3 = sun is visible in summer. In the monsoon, the sun is hidden by clouds.

Let N be the list of unique words = [‘monsoon’, ‘rain’, ‘come’, ‘again’, ‘sun’, ‘visible’, ‘summer’, ‘hidden’, ‘clouds’]

计数矩阵的维度将是 3X9,因为语料库中有 3 个文档和 9 个唯一词。
计数矩阵如下所示:

优点:由于只考虑单词的频率,因此计算成本较低。


缺点:由于计算只是基于计数并且没有考虑单词的上下文,因此该方法证明不太有用。
代码:

#Importing libraries
from sklearn.feature_extraction.text import CountVectorizer
import nltk 
from nltk.corpus import stopwords 
from nltk.tokenize import word_tokenize 

#Downloading stopwords and punkt packages
nltk.download('stopwords') 
nltk.download('punkt') 

#Initialising stopwords for english
set(stopwords.words('english')) 

#sample sentences
text = ["In monsoon, it will rain", "rain rain come again", "sun is visible in summer. In the monsoon, the sun is hidden by clouds"]

#set of stop words
stop_words = set(stopwords.words('english')) 
all_sentences = []

#Logic for removing stop words and obtaining filtered sentences from the list 

for i in range(len(text)):
  word_tokens[i] = word_tokenize(text[i]) 
  tokenized_sentence = []

  for j in word_tokens[i]: 
      if j not in stop_words: 
          tokenized_sentence.append(j) 
  all_sentences.append(" ".join(tokenized_sentence))

#Initialising the CountVectorizer
countvectorizer = CountVectorizer()

#Applying CountVectorizer to the list of sentences
X = countvectorizer.fit_transform(all_sentences)

#Converting output to array
result = X.toarray()

print("Sentences after removing stop words", all_sentences)
print("Count Vector:", result)

2.TF-IDF:

TF-IDF 代表词频-逆文档频率。 该方法是对 Count Vector 方法的即兴创作,因为特定单词的频率被考虑在整个语料库中,而不仅仅是单个文档。 主要思想是对某些文档非常具体的词给予更多的权重,而对更普遍且在大多数文档中出现的词给予较少的权重。

例如,诸如“is”、“the”、“and”之类的通用词会经常出现,而诸如“Donald Trump”或“Indira Gandhi”之类的词将特定于特定文档。

数学上,

词频 (TF) = 词条在文档中出现的次数 / 文档中词条的总数

逆文档频率 (IDF) = log(N/n) 其中 N 是文档总数,n 是一个术语出现的文档数。

考虑以下示例。
给出了两个文档——D1 和 D2。

TF(Today, Document 1) = 1/8

TF(Today, Document 2) = 1/8

TF(sunny, Document 1) = 4/8

IDF(Today) = log(2/2) = log(1) = 0

IDF(sunny) = log(2/1) = log(2) = 0.301

Therefore,

TF-IDF(Today, Document 1) = 1/8 * 0 = 0

TF-IDF(Today, Document 2) = 1/8 * 0 = 0

TF-IDF(sunny, Document 1) = 4/8 * 0.301 = 0.1505

从上面的计算可以看出,与文档 1 的上下文中的重要词“sunny”相比,常用词“Today”的权重较低。

优点:

它在计算上很容易。
文档中最重要的单词是通过基本计算提取的,不需要太多努力。

缺点:

它无法捕捉单词的语义,只能像词汇级别的特征一样工作。
代码:

from sklearn.feature_extraction.text import TfidfVectorizer 
import pandas as pd

#Declaring the list of sentences
documents = ['Today is sunny day', 'Today is rainy day']

#Initialising Tfidf Vectorizer
vectorizer = TfidfVectorizer()

#Fitting the Vectorizer to the list
X = vectorizer.fit_transform(documents)
print(X)

#Printing the feature names
print(vectorizer.get_feature_names()) 

matrix = X.todense()
tfidf_list = matrix.tolist()
tfidf_df = pd.DataFrame(tfidf_list, columns = vectorizer.get_feature_names())

print(tfidf_df)

3.Word2Vec:

Word2Vec 是一种基于预测的词嵌入方法。 与确定性方法不同,它是一个浅层的两层神经网络,能够预测单词之间的语义和相似性。 Word2Vec 是两种不同模型的组合——(i)CBOW(连续词袋)和(ii)Skip-gram。

模型概述 – CBOW(连续词袋)和 Skip-gram。

word_2_vec

3.1 CBOW(连续词袋):

该模型是一个浅层神经网络,可以在给定上下文的情况下预测单词的概率。 这里,上下文是指围绕要预测的单词的单词的输入。
CBOW模型的架构:

Architecture of CBOW model

作为第一步,输入是通过为给定文本形成一个词袋来创建的。
例如,

Sentence 1 = All work and no play make Jack a dull boy.

Sentence 2 = Jack and Jill went up the hill.

Bag of Words: {“All”:1, “work”:1, “no”:1, “play”:1, “makes”:1, “Jack”:2, “dull”:1, “boy”:1, “Jill”:1, “went”:1, “up”:1, “hill”:1} (after removing the stop words)

这个由单词及其出现频率组成的输入作为向量发送到输入层。对于 X 个单词,输入将是 X[1XV] 个向量,其中 V 是向量的最大长度。

接下来,输入隐藏层矩阵由维数 VXN 组成,其中 N 是表示单词的维数。输出隐藏层矩阵由维数 NXV 组成。在这里,这些值是通过将输入乘以隐藏输入权重来计算的。

在输出层,通过将隐藏输入乘以隐藏输出权重来计算输出。在隐藏层和输出层之间计算的权重给出了单词的表示。作为一个连续的中间步骤,通过对输出和目标值之间计算的误差使用反向传播来调整权重。
优点:

与确定性方法相比,概率性方法给出了更好的结果。
由于不需要计算巨大的矩阵,因此内存需求较少。
缺点:

优化非常重要,否则培训将需要很长时间才能完成。


3.2 Skip-gram :

Skip-gram 模型预测给定单词的上下文,与 CBOW 所做的正好相反。 Skip-gram 模型的架构:

Architecture of Skip-gram model:

输入层大小:[1XV],输入隐藏权重矩阵大小:[VXN],输出隐藏权重矩阵:[NXV],输出层大小:C[1XV]

模型的输入和直到隐藏层的进一步步骤将类似于 CBOW。 输出目标变量的数量取决于上下文窗口的大小。 例如,如果上下文窗口的大小为 2,那么将有四个目标变量,两个词在给定词之前,两个词在给定词之后。

将针对四个目标变量计算四个单独的误差,并通过执行元素相加获得最终向量。 然后反向传播这个最终向量以更新权重。 对于训练,输入和隐藏层之间的权重用于单词表示。

优点:

Skip-gram 模型可以捕获单词的不同上下文信息,因为每个上下文都有不同的向量表示。
对于不常用的术语更准确,并且适用于更大的数据库。
缺点:

它需要更多的 内存 进行处理。
代码:

要使用 genism 库中预训练的 Word2Vec 模型:

import gensim 
import gensim.downloader as api
from gensim.models.keyedvectors import KeyedVectors

#loading pretrained model
nlp_w2v = api.load("word2vec-google-news-300") 

#save the Word2Vec model
nlp_w2v.wv.save_word2vec_format('model.bin', binary=True)

#load the Word2Vec model 
model = KeyedVectors.load_word2vec_format('model.bin', binary=True)

#Printing the most similar words to New York from vocabulary of pretrained model
model.most_similar('New_York')

从头开始训练 Word2Vec 模型:

import gensim 
'''
Data for training Word2Vec
train: A data frame comprising of text samples
'''

#training data
corpus = train

#creates a list for a list of words for every training sample
w2v_corpus = []
for document in corpus:
   w2v_words = document.split()
   w2v_grams = [" ".join(w2v_words[i:i+1]) 
               for i in range(0, len(w2v_words), 1)]
   w2v_corpus.append(w2v_grams)

#initialising and training the custom Word2Vec model 
'''
size: dimensions of word embeddings 
window: context window for words 
min_count: words which appear less number of times than this count will be ignored 
sg: To choose skip-gram model 
iter: Number of epochs for training
'''

word2vec_model = gensim.models.word2vec.Word2Vec(w2v_corpus, size=300,   
            window=8, min_count=1, sg=1, iter=30)

#vector size of the model
print(word2vec_model.vector_size)

#vocabulary contained by the model
print(len(word2vec_model.wv.vocab))

4.GloVE:

GloVe 代表词表示的全局向量。 该算法是对 Word2Vec 方法的改进,因为它考虑全局统计而不是局部统计。 在这里,全局统计数据意味着从整个语料库中考虑的单词。 GloVe 基本上试图解释特定单词对在文档中出现的频率。 为此,构建了一个共现矩阵,该矩阵将表示特定单词相对于另一个单词的存在。

例如,

Corpus – It is rainy today, tomorrow it will be sunny and the day after will be windy.

上面的矩阵表示一个共现矩阵,其值表示在给定示例语料库中一起出现的每对单词的计数。

在计算给定“today”、p(rainy/today) 和给定“tomorrow”、p(rainy/tomorrow) 的单词“rainy”的出现概率后,结果是与“rainy”最相关的单词 与“明天”相比,“今天”是“今天”。

代码:

#Import statements
from numpy import array
from numpy import asarray
from numpy import zeros
from keras.preprocessing.text import Tokenizer 

#Download the pretrained GloVe data files
!wget http://nlp.stanford.edu/data/glove.6B.zip

#Unzipping the zipped folder
!unzip glove*.zip

#Initialising a tokenizer and fitting it on the training dataset
'''
train: a dataframe comprising of rows containing text data
'''
tokenizer = Tokenizer(num_words=5000)
tokenizer.fit_on_texts(train)

#Creating a dictionary to store the embeddings
embeddings_dictionary = dict()

#Opening GloVe file
glove_file = open('glove.6B.50d.txt', encoding="utf8")

#Filling the dictionary of embeddings by reading data from the GloVe file
for line in glove_file:
    records = line.split()
    word = records[0]
    vector_dimensions = asarray(records[1:], dtype='float32')
    embeddings_dictionary[word] = vector_dimensions
glove_file.close()

#Parsing through all the words in the input dataset and fetching their corresponding vectors from the dictionary and storing them in a matrix 
embedding_matrix = zeros((vocab_size, 50))
for word, index in tokenizer.word_index.items():
    embedding_vector = embeddings_dictionary.get(word)
    if embedding_vector is not None:
        embedding_matrix[index] = embedding_vector

#Displaying embedding matrix 
print(embedding_matrix) 

结论:

在这篇博客中,我们回顾了一些方法——Count Vector、TF-IDF、Word2Vec 和 GloVe,用于从原始文本数据创建词嵌入。 预处理文本然后发送预处理数据以创建词嵌入总是一个好习惯。 作为进一步的步骤,这些词嵌入可以发送到机器学习或深度学习模型,用于各种任务,例如文本分类或机器翻译。

作者 east
深度学习 4月 2,2022

Tensorflow:使用 GPU 进行 BERT 微调

训练数据的短缺是自然语言处理面临的最大挑战之一。 因为 NLP 是一个多元化的领域,在多语言数据中具有多种任务。 最特定于任务的数据集仅包含几千个训练数据,这不足以实现更好的准确性。

为了提高现代基于深度学习的 NLP 模型的性能,需要数百万或数十亿的训练数据。 研究人员已经开发出各种方法来使用网络上的大量未注释文本来训练通用语言表示模型。 这称为预训练。

这些预训练模型可用于为广泛的 NLP 任务(例如问答和测试分类)创建最先进的模型。 它被称为微调。 当我们没有足够数量的训练样本时,微调是有效的。

BERT

BERT 代表来自 Transformers 的双向编码器表示。 BERT 是由 Google AI 的研究人员推出的 NLP 框架。 它是一种新的预训练语言表示模型,可在各种自然语言处理 (NLP) 任务上获得最先进的结果。 只需添加单个输出层即可对预训练的 BERT 模型进行微调。 你可以在这里找到 BERT 的学术论文:https://arxiv.org/abs/1810.04805。

在本教程中,您将通过一个示例学习对 BERT 模型进行微调。 可以参考之前的 BERT 教程,里面已经解释了 BERT 模型的架构。

我们将使用 Kaggle 的 Quora Insincere Questions Classification 任务数据进行演示。

In [1]:
# Let's load the required packages
import pandas as pd
import numpy as np
import datetime
import zipfile
import sys
import os

下载预训练的 BERT 模型以及模型权重和配置文件

In [2]: !wget storage.googleapis.com/bert_models/2018_10_18/uncased_L-12_H-768_A-12.zip

提取下载的模型 zip 文件。

In [3]:
repo = 'model_repo'
if not os.path.exists(repo):
    print("Dir created!")
    os.mkdir(repo)
with zipfile.ZipFile("uncased_L-12_H-768_A-12.zip","r") as zip_ref:
    zip_ref.extractall(repo)
In [4]:
BERT_MODEL = 'uncased_L-12_H-768_A-12'
BERT_PRETRAINED_DIR = f'{repo}/uncased_L-12_H-768_A-12'

OUTPUT_DIR = f'{repo}/outputs'
if not os.path.exists(OUTPUT_DIR):
    os.makedirs(OUTPUT_DIR)

print(f'***** Model output directory: {OUTPUT_DIR} *****')
print(f'***** BERT pretrained directory: {BERT_PRETRAINED_DIR} *****') 

Out[4]:
***** Model output directory: model_repo/outputs *****
***** BERT pretrained directory: model_repo/uncased_L-12_H-768_A-12 *****

准备和导入 BERT 模块

以下 BERT 模块是从 GitHub 克隆源代码并导入模块。

In [5]:
# Download the BERT modules
!wget raw.githubusercontent.com/google-research/bert/master/modeling.py 
!wget raw.githubusercontent.com/google-research/bert/master/optimization.py 
!wget raw.githubusercontent.com/google-research/bert/master/run_classifier.py 
!wget raw.githubusercontent.com/google-research/bert/master/tokenization.py
!wget raw.githubusercontent.com/google-research/bert/master/run_classifier_with_tfhub.py
In [6]: # Import BERT modules 
import modeling 
import optimization 
import run_classifier 
import tokenization 
import tensorflow as tf 
import run_classifier_with_tfhub

准备训练数据

在这里,我们将在一小部分训练数据上训练 BERT 模型。

In [7]:
from sklearn.model_selection import train_test_split

train_df =  pd.read_csv('input/train.csv')
train_df = train_df.sample(2000)                 # Train on 2000 data

train, val = train_test_split(train_df, test_size = 0.1, random_state=42)

train_lines, train_labels = train.question_text.values, train.target.values
val_lines, val_labels = val.question_text.values, val.target.values

label_list = ['0', '1']
In [8]:
def create_examples(lines, set_type, labels=None):
    guid = f'{set_type}'
    examples = []
    if guid == 'train':
        for line, label in zip(lines, labels):
            text_a = line
            label = str(label)
            examples.append(
              run_classifier.InputExample(guid=guid, text_a=text_a, text_b=None, label=label))
    else:
        for line in lines:
            text_a = line
            label = '0'
            examples.append(
              run_classifier.InputExample(guid=guid, text_a=text_a, text_b=None, label=label))
    return examples

指定 BERT 预训练模型。

这里使用的是 uncased_L-12_H-768_A-12 型号。 该模型由12层、768个隐藏、12个头、110M个参数组成。 它是一个 Uncased 模型,这意味着文本在标记化之前已被小写。

In [9]:
BERT_MODEL = 'uncased_L-12_H-768_A-12' 
BERT_MODEL_HUB = 'https://tfhub.dev/google/bert_' + BERT_MODEL + '/1'

初始化模型超参数。

In [10]:
TRAIN_BATCH_SIZE = 32
EVAL_BATCH_SIZE = 8
LEARNING_RATE = 2e-5
NUM_TRAIN_EPOCHS = 3.0
WARMUP_PROPORTION = 0.1
MAX_SEQ_LENGTH = 128

# Model Configuration
SAVE_CHECKPOINTS_STEPS = 1000 
ITERATIONS_PER_LOOP = 1000
NUM_TPU_CORES = 8

VOCAB_FILE = os.path.join(BERT_PRETRAINED_DIR, 'vocab.txt')
CONFIG_FILE = os.path.join(BERT_PRETRAINED_DIR, 'bert_config.json')
INIT_CHECKPOINT = os.path.join(BERT_PRETRAINED_DIR, 'bert_model.ckpt')
DO_LOWER_CASE = BERT_MODEL.startswith('uncased')

tpu_cluster_resolver = None   # Model trained on GPU, we won't need a cluster resolver

def get_run_config(output_dir):
    return tf.contrib.tpu.RunConfig(
    cluster=tpu_cluster_resolver,
    model_dir=output_dir,
    save_checkpoints_steps=SAVE_CHECKPOINTS_STEPS,
    tpu_config=tf.contrib.tpu.TPUConfig(
        iterations_per_loop=ITERATIONS_PER_LOOP,
        num_shards=NUM_TPU_CORES,
        per_host_input_for_training=tf.contrib.tpu.InputPipelineConfig.PER_HOST_V2))

加载分词器模块

注意:当您使用 Cased 模型时,传递 do_lower_case = False。

In [11]:
tokenizer = tokenization.FullTokenizer(vocab_file=VOCAB_FILE, do_lower_case=DO_LOWER_CASE)
train_examples = create_examples(train_lines, 'train', labels=train_labels)

# compute number of train and warmup steps from batch size
num_train_steps = int( len(train_examples) / TRAIN_BATCH_SIZE * NUM_TRAIN_EPOCHS)
num_warmup_steps = int(num_train_steps * WARMUP_PROPORTION)

微调来自 TF Hub 的预训练 BERT 模型

本节说明了来自 TensorFlow 集线器模块的微调预训练 BERT 模型。

In [12]:

model_fn = run_classifier_with_tfhub.model_fn_builder(
  num_labels=len(label_list),
  learning_rate=LEARNING_RATE,
  num_train_steps=num_train_steps,
  num_warmup_steps=num_warmup_steps,
  use_tpu=False,
  bert_hub_module_handle=BERT_MODEL_HUB
)

estimator_from_tfhub = tf.contrib.tpu.TPUEstimator(
  use_tpu=False,    #If False training will fall on CPU or GPU
  model_fn=model_fn,
  config=get_run_config(OUTPUT_DIR),
  train_batch_size=TRAIN_BATCH_SIZE,
  eval_batch_size=EVAL_BATCH_SIZE,
)
In [13]:
# Train the model
def model_train(estimator):
    print('Please wait...')
    train_features = run_classifier.convert_examples_to_features(
      train_examples, label_list, MAX_SEQ_LENGTH, tokenizer)
    print('***** Started training at {} *****'.format(datetime.datetime.now()))
    print('  Num examples = {}'.format(len(train_examples)))
    print('  Batch size = {}'.format(TRAIN_BATCH_SIZE))
    tf.logging.info("  Num steps = %d", num_train_steps)
    train_input_fn = run_classifier.input_fn_builder(
      features=train_features,
      seq_length=MAX_SEQ_LENGTH,
      is_training=True,
      drop_remainder=True)
    estimator.train(input_fn=train_input_fn, max_steps=num_train_steps)
    print('***** Finished training at {} *****'.format(datetime.datetime.now()))
In [14]: model_train(estimator_from_tfhub)
In [15]:
# Evaluate the model
def model_eval(estimator):
    
    eval_examples = create_examples(val_lines, 'test')
    
    eval_features = run_classifier.convert_examples_to_features(
        eval_examples, label_list, MAX_SEQ_LENGTH, tokenizer)
        
    print('***** Started evaluation at {} *****'.format(datetime.datetime.now()))
    print('  Num examples = {}'.format(len(eval_examples)))
    print('  Batch size = {}'.format(EVAL_BATCH_SIZE))
    
    eval_steps = int(len(eval_examples) / EVAL_BATCH_SIZE)
    
    eval_input_fn = run_classifier.input_fn_builder(
      features=eval_features,
      seq_length=MAX_SEQ_LENGTH,
      is_training=False,
      drop_remainder=True)
    
    result = estimator.evaluate(input_fn=eval_input_fn, steps=eval_steps)
    
    print('***** Finished evaluation at {} *****'.format(datetime.datetime.now()))
    
    print("***** Eval results *****")
    for key in sorted(result.keys()):
        print('  {} = {}'.format(key, str(result[key])))
In [16]: model_eval(estimator_from_tfhub)

从检查点微调预训练的 BERT 模型

您还可以从保存的检查点加载预训练的 BERT 模型。

In [17]:
CONFIG_FILE = os.path.join(BERT_PRETRAINED_DIR, 'bert_config.json')
INIT_CHECKPOINT = os.path.join(BERT_PRETRAINED_DIR, 'bert_model.ckpt')

OUTPUT_DIR = f'{repo}/outputs_checkpoints'
if not os.path.exists(OUTPUT_DIR):
    os.makedirs(OUTPUT_DIR)

model_fn = run_classifier.model_fn_builder(
    bert_config=modeling.BertConfig.from_json_file(CONFIG_FILE),
    num_labels=len(label_list),
    init_checkpoint=INIT_CHECKPOINT,
    learning_rate=LEARNING_RATE,
    num_train_steps=num_train_steps,
    num_warmup_steps=num_warmup_steps,
    use_tpu=False, #If False training will fall on CPU or GPU, 
    use_one_hot_embeddings=True)

estimator_from_checkpoints = tf.contrib.tpu.TPUEstimator(
    use_tpu=False,
    model_fn=model_fn,
    config=get_run_config(OUTPUT_DIR),
    train_batch_size=TRAIN_BATCH_SIZE,
    eval_batch_size=EVAL_BATCH_SIZE)
In [18]: 
# Train the Model
model_train(estimator_from_checkpoints)
# Evaluate the Model
In [19]: model_eval(estimator_from_checkpoints)
作者 east
深度学习 4月 2,2022

BERT:如何处理长文档

BERT 的问题

BERT,即 Transformers 的双向编码器表示,目前是公众可以使用的最著名的预训练语言模型之一。事实证明,它在包括问答和分类在内的各种任务中非常有用。

但是,BERT 最多只能接受长度为 512 个标记的输入序列。这是一个很大的限制,因为许多常见的文档类型都比 512 个单词长得多。在这一点上,我们将解释和比较一些方法来克服这个限制,并使您更容易使用 BERT 处理更长的输入文档。

为什么 BERT 不能处理长文档?

BERT 继承了转换器的架构,转换器本身使用自注意力、前馈层、残差连接和层规范化作为其基础组件。如果您不熟悉变压器架构,您可以阅读Deep Learning 101: What is a Transformer and Why Should I Care? 在继续读本文之前。

bertarchitecture.png

BERT 和长输入文档的问题源于 BERT 架构的几个领域。

Transformer 本身是自回归的,BERT 的创建者指出,当使用超过 512 个令牌的文档时,性能会显着下降。所以,这个限制是为了防止低质量的输出。
自注意力模型的空间复杂度为 O(n²)。像这样的二次复杂性使得这些模式非常耗费资源进行微调。输入的时间越长,微调模型所需的资源就越多。二次复杂度使大多数用户的成本高得令人望而却步。
鉴于上述两点,BERT 使用基于较短输入序列的位置编码进行了预训练。这意味着该模型不能很好地推广到更长的序列,并且为收益递减而进行微调的费用意味着解决这个问题的方法有限。
但是我的文件很长,那我现在该怎么办?

幸运的是,您可以做一些事情来有效地使用 BERT 处理更长的输入文档。这里有一些经过验证的技术可以尝试。

修整输入序列

这可能是处理 BERT 和长输入文档时最常用的技术。鉴于 BERT 对多达 512 个令牌的文档表现良好,只需将较长的文档拆分为 512 个令牌块即可让您将长文档分段传递。

对于较长的连续文档(例如长新闻文章或研究论文),将完整长度的文档切成 512 个字块不会造成任何问题,因为文档本身组织良好并且专注于单个主题。但是,如果您的文本块不太连续(例如聊天机器人脚本或一系列推文),则中间可能有与核心主题无关的块。

平均段输出的投票

另一种常见的技术是将长文档分成相等长度的重叠段,并使用投票机制进行分类。这将缓解诸如对话记录之类的非连续文档所带来的问题。使用来自较大文档的各个块的投票将合并来自整个事物的信息。

这在实践中的工作方式是将文档分成段,并通过 BERT 运行每个段,以获得分类 logits。然后通过组合投票(每段一个),我们可以得到一个平均值,我们将其作为最终分类。

这里的缺点是你不能在任务上微调 BERT,因为损失是不可微的。即使存在重叠,您也会错过每个段之间的一些共享信息。这可能会产生特定于分析管道架构的下游影响。

结论

对长输入文档使用 BERT 取决于您的具体任务。有一些更新的模型——比如 RoBERTa——是为了解决 BERT 的弱点而创建的。我们将在以后的帖子中更多地讨论这些内容。对于需要来自整个文档的信息的复杂任务,或者您使用的是非连续文档,使用像 RoBERTa 这样的 BERT 变体可能是最佳解决方案。

作者 east
深度学习 3月 31,2022

BERT 模型的深度揭秘

2018 年,Google 提出了一种特殊的语言表示模型,称为“BERT”,代表“来自 Transformers 的双向编码器表示”。 以前的语言表示模型(例如 OpenAI GPT)使用单向方法(从左到右)来编码序列。 然而,这种方法是有限的,因为上下文只能从一个方向学习。

例如,考虑到这句话——“ The man was looking at the cloudy sky. The man witnessed a cloudy state of mind for the whole day 。” 在这里,无论考虑上下文或句子中单词的实际含义,之前的模型都会产生相同的单词“cloudy”嵌入。 而对于 BERT 模型,“多云”一词将根据不同的上下文具有不同的嵌入。

该模型在现实生活中的主要应用之一是提高对谷歌搜索引擎的查询理解。 早些时候,搜索引擎是基于关键字的,无法考虑可以提出相同问题的各种格式。 因此,在搜索引擎中使用 BERT 有助于显着改善查询结果。

BERT Example

需要注意的重要一点是,BERT 不是一种新的架构设计,而是一种新的训练策略。 由于 BERT 使用了论文中提出的 Transformer 的编码器部分——Attention Is All You Need,我们将花一些时间首先了解相同的内容,然后再讨论 BERT 不同阶段的详细工作。

变换器 – 编码器

1.1 简单多头注意力机制:

Transformer 中使用的最重要的概念是“注意”机制。 让我们看看下面的图片:

当我们第一次看到图像时,我们的大部分注意力都被绿色人物——自由女神像所吸引。

同样,当提供上下文(查询)时,我们不应该对每个输入给予同等的重视,而应该更多地关注一些重要的输入。

在这里,如果查询是关于建筑物的,那么我们的注意力就会放在背景上。

因此,我们将输入一个称为 Z 的新项,而不是普通的原始输入 x 到一个层,这将是所有单个输入 xi 的加权和。

在数学上它表示为,

其中 ai 是决定注意力的个体权重。

为了更好地理解注意力的概念,让我们引入以下变量——Q、K、V。Q 代表 Query,这是我们试图查看的上下文,Value 表示给定的输入(像素或文本特征), Key 是 Value 的编码表示。

例如,在上图中,如果:

Query = 绿色

Key=建筑

那么价值将是,

因此,为了形成对输入的注意力,我们需要将查询和键相关联并删除不相关的值。

再次考虑这个例子,

| The man was looking at the cloudy sky 。 (字数 = 8)

由于有 8 个单词,我们将有 8 个查询、8 个键和 8 个值。

Q = 8X512、K^T = 512X8、V = 8X512 和最后 d_k = 512 的维度。512 是作为输入馈送到编码器的固定维度数。

在等式中,Q 和 K 矩阵之间的点积将导致它们之间的相似度同时生成,而不是单独计算每个单词的相似度。 此外,我们在分母中有一个维度数的平方根,以便缩放完整值。 这将有助于确保顺利进行训练。

刚才我们理解的是简单的注意力,现在让我们继续理解
multi-head 注意力是什么意思?

多头注意力是转换器使用的一项功能,它为每个查询生成 h 个注意力,而不是一个注意力。使用 h attention 的主要原因是为特定查询获得 h 个不同的视角。考虑这么多角度将大大提高模型的整体准确性。对于输出,将所有 h 个注意力连接起来,然后输入到点积方程中。

1.2 跳过连接和层规范化:

编码器的另一个主要组成部分是跳过连接和归一化层。

跳过连接基本上是通过跳过中间的一些层将一层连接到另一层的残差块。引入跳跃连接的想法是解决深度神经网络中的退化问题(梯度消失)。跳过连接有助于网络的最佳训练。

层归一化类似于批量归一化,除了在层归一化中,归一化发生在同一层中的特征上。

下图展示了编码器的结构,展示了multi-head 注意力、跳过连接和层归一化的使用。

1.3 前馈网络:

如上图所示,层归一化的输出被馈送到一个全连接层、ReLU 层和另一个全连接层。这些操作分别应用于每个位置,因为每个输出都依赖于与其相关的相应注意力。

通过以上部分,您对编码器中存在的不同模块及其使用有了基本的了解。

在下一节中,让我们继续了解 BERT 的强大功能。

BERT 模型:

使用 BERT 的动机是解决这两个主要挑战:

对所有单词的深刻上下文理解。与转换器不同,它尝试实现双向词嵌入策略。
一个可以服务于多种目的的单一模型,因为从头开始为每个单独的任务进行训练,在计算上既昂贵又耗时。

理解输入:

输入包括分成标记的句子——T1、T2、… Tn。一开始,总是有一个 [CLS] 令牌。如果输入中有多个序列,则它们被 [SEP] 标记分割。输出令牌的数量与输入令牌的数量相同。请看下图以更好地理解。

输入嵌入包括三种——令牌嵌入、段嵌入和位置嵌入。

1、令牌嵌入——为了计算嵌入,输入令牌使用固有词汇表(大小 – 30,000 个令牌)转换为单词片段。 例如,“bullying”这个词将被拆分为“bully”和“ing”。
2、Segment Embeddings——这些嵌入确保了每个标记的序列标记,以确定标记属于哪个序列。 为了做到这一点,嵌入值添加了一个常量偏移量,其值决定了它所属的序列。
3、 位置嵌入——这有助于跟踪令牌的位置。

最终的嵌入将是 Token 嵌入、Segment 嵌入和位置嵌入的总和。

预训练和微调任务:

BERT 模型包括两个阶段——预训练和微调。

在预训练阶段,该模型使用两个 NLP 任务进行训练——(i) 掩蔽语言模型 (MLM) 和 (ii) 下一句预测 (NSP)。使用 Masked LM,解码器生成输入的向量表示,其中包含一些掩码单词。

例如,如果输入句子是——“ my cat is furry ”,那么掩码向量看起来像——“ my cat is  [MASK]”。

在这种策略中,80% 的时间单词会被屏蔽。 10% 的情况下,它会被一个随机词替换——“ my cat is human ”。在剩下的 10% 的时间里,这个词保持不变——“ my cat is furry ”。这种学习方法将使模型变得健壮,因为它将提高预测准确性。需要注意的一点是,模型不会被评估预测整个序列,而只会评估缺失的单词。

第二个 NLP 任务是 Next Sentence Prediction (NSP)。输入将包含两个句子——A 和 B。这个想法是预测第二个句子是否是第一个句子的后续。这样,模型将能够学习两个句子之间的关系。模型有 50% 的时间是连续的句子,其余 50% 的序列是随机设置的。查看下图以获取 NSP 任务的示例。

总而言之,这两个训练任务能够丰富学习序列的上下文信息和语义。

BERT 模型可以针对许多不同的任务进行微调——自然语言推理 (NLI)、问答、情感分析、文本分类等。在微调的同时,我们保持完整的架构相同,除了最后一层将在自定义数据上训练模型。添加一个浅层分类器或解码器可以完成这项工作。

预训练模型:

BERT 论文提出了以下预训练模型:-

BERT-Base, Uncased:12 层,768 隐藏,12 注意力头,110M 参数
BERT-Large, Uncased:24 层,1024 隐藏,16 注意力头,340M 参数

BERT-Base,Cased:12 层,768 隐藏,12 注意力头,110M 参数
BERT-Large,Cased:24 层,1024 隐藏,16 注意力头,340M 参数

代码实现:

现在,让我们使用 BERT 实现一个多标签文本分类模型。

多标签文本分类概述

那么,什么是多标签文本分类?它基本上是将文本分类为它所属的一个或多个类别。例如,考虑电影《神奇女侠》的影评——“在一个痴迷于有缺陷的英雄、不受欢迎的英雄和反英雄的娱乐环境中,戴安娜毫无歉意地是一个真正的英雄”。从这段文字可以预测,这部电影属于“奇幻”、“冒险”和“科幻”的类型。

因此,为了解决多标签分类任务,第一步是创建由清洁文本和单热编码目标向量组成的数据。例如,在上述情况下,目标向量可能看起来像 – [0,0,1,0,1,0,1,0,0…] 其中 1 代表类别 – 幻想、冒险和科幻,而 0代表剩余的缺席类别。第二步是创建词嵌入,最后在这些嵌入上训练模型。

使用 BERT 进行多标签文本分类:

第 1 步:安装:

使用以下命令在 google colab 上安装 simpletransformers 库:

!pip install simpletransformers

Simpletransformers 是一个建立在著名的变形金刚库 – Hugging Face 之上的库。这使得只使用几行代码就可以进行预处理、训练和评估。

第 2 步:加载和预处理数据:

我们将致力于有毒评论分类的 kaggle 挑战,其中文本需要分为六个类别——有毒、严重有毒、淫秽、威胁、侮辱和身份仇恨。数据集可以从这里下载。将下载的文件存储在您当前的工作目录中。我们将使用 train.csv 文件来创建训练和评估数据。

# Import statements

import pandas as pd
from sklearn.model_selection import train_test_split
from simpletransformers.classification import MultiLabelClassificationModel

# ’dir’ would be your current working directory
df = pd.read_csv('dir/train.csv') 
# taking nearly 15,000 samples out of nearly 1,50,000 samples
df= df.sample(frac=0.1) 

# Combining all the tags into a single list
df['labels'] = df[df.columns[2:]].values.tolist() 

# Removing '\n' from the text
df['text'] = df['comment_text'].apply(lambda x: x.replace('\n', ' ')) 

# Creating new dataframe consisting of just text and their labels
new_df = df[['text', 'labels']].copy() 

# Splitting the data into training and testing sets, 80% of data is kept for training and 20% for evaluation
train, eval = train_test_split(new_df, test_size=0.2)

第 3 步:加载预训练的 BERT 模型:

在这里,我们将使用 roberta 模型的预训练“roberta-base”版本。 RoBERTa 代表 Robustly Optimized BERT Pretraining Approach。 由于原始 BERT 模型的以下变化,RoBERTa 提高了性能——更长的训练、使用更多数据以及更长的训练序列、动态掩码模式以及从预训练任务中删除下一句预测目标。

'''
Description of params:
model_type: type of the model from the following {'bert', 'xlnet', 'xlm', 'roberta', 'distilbert'}

model_name: choose from a list of current pretrained models {roberta-base, roberta-large} roberta-base consists of 12-layer, 768-hidden, 12-heads, 125M parameters.
num_labels: number of labels(categories) in target values

args: hyperparameters for training. max_seq_length truncates the input text to 512. 512 because that is the standard size accepted as input by the model.
'''
model = MultiLabelClassificationModel('roberta', 'roberta-base', num_labels=6, args={'train_batch_size':2, 'gradient_accumulation_steps':16, 'learning_rate': 3e-5, 'num_train_epochs': 2, 'max_seq_length': 512})

步骤4:训练模型

# train_model is an inbuilt function which directly trains the data with the specified parameter args. Output_dir is the location for the model weights to be stored in your directory.

model.train_model(train, multi_label=True, output_dir='/dir/Output')

步骤5:评估模型

'''
Description of params: 

result: Label Ranking Average Precision (LRAP) is reported in the form of a dictionary 
model_outputs: Returns model predictions in the form of probabilities for each sample in the evaluation set
wrong_predictions: Returns a list for each incorrect prediction

'''

# eval_model is an inbuilt method which performs evaluation on the eval dataframe
result, model_outputs, wrong_predictions = model.eval_model(eval) 

# Converting probabilistic scores to binary - 0/1 values using 0.5 as threshold
for i in range(len(model_outputs)):
  for j in range(6):
    if model_outputs[i][j]<0.5:
      model_outputs[i][j] = 0
    else:
      model_outputs[i][j] = 1

第 6 步:预测:

test.csv 文件也将从此处下载到数据集中。 它只包含文本,不包含标签。

# Reading the test data for prediction
test_data = pd.read_csv('dir/test.csv')

# Replacing '\n' values in the text
predict_data = test_data.comment_text.apply(lambda x: x.replace('\n', ' '))

# Convert the dataframe to a list as the predict function accepts a list
predict_data = predict_data.tolist()

# Makes predictions for the test data
predictions, outputs = model.predict(predict_data) 

结论:

在本文中,我们深入探讨了 BERT 模型。 我们还对变压器使用的编码器模块有了基本的了解。 BERT 模型由于其双向编码的特性而被证明比其他以前的模型具有优势。 该模型经过预训练,可以针对自然语言推理 (NLI)、情感分析、多类/多标签文本分类等多项任务进行微调。 该模型通过大幅减少针对不同目的的不同模型从头开始训练的需求,无疑提高了多个领域的准确性。

作者 east
深度学习 3月 31,2022

为什么google应用bert模型到搜索及如何SEO

随着新BERT算法的实现,谷歌已经在谷歌搜索中出现的结果进行了另一种重要的排序调整。了解BERT算法更新对搜索结果造成的哪些更改,还有哪些方面没有造成改变, 对于SEO维护搜索中现有的结果至关重要,以及在搜索中建立新的排名。

谷歌不断调整其超级秘密搜索算法。一般来说,这些调整很小,不足导致大量搜索结果突然变化。 但BERT更新并非如此。BERT代表了Google对搜索结果内容策略有了地震般转变,肯定会影响每个公司的内容展示结果和SEO的方法。

随着BERT算法的引入,许多公司将看到搜索结果的突然变化,无论好坏。并考虑到许多公司今天接近内容营销的方式,“更糟糕的”案例可能更有可能。

什么是bert算法?

那么,BERT是什么,为什么现在改变?使用Google的Pandu Nayak,Google Clower和副总裁最近的博客文章的参考,最好回答这个问题,搜索谷歌搜索。来自他的博客文章:“随着我们研究团队的最新进展,在语言理解的科学中 – 通过机器学习使得可以实现重大改进,我们如何理解查询,代表过去五年中最大的飞跃和搜索历史上的最大跳跃之一。“

机器学习,解释模式和语音过程的数学方式和语言语言,正在推进搜索科学。该进步的一个结果是BERT,它代表来自变压器的双向编码器表示。根据Nayak的说法,“[BERT]使任何人能够培养自己的最先进的问题回答系统。”

在这篇文章的剩余部分中,我将更多地挖掘这个主题以及伯特将如何影响您的SEO和内容开发方法。以及这种变化如何改变您的短期和长期可见性和在搜索中的存在。

什么是机器学习?

根据Google的说法,Transformers (the “T” in BERT)是根据句子中的所有其他单词,而不是一个逐个地处理词语的模型。“这意味着BERT机器学习模型现在将通过检查之前和之后的单词来解析查询中的句子或短语的完整上下文。根据Google,这种上下文分析,而不是与主题的特定关键字关联,是了解搜索查询背后的意图的卓越过程。结果是Google的SEO更进一步的方法。

特别是关于以较长的对话为中心的查询,在当今由基于语音的设备驱动的搜索设备中变得越来越常见,如亚马逊的Alexa或Apple的Siri等,机器学习算法将能够更好地了解理解介词用于限定查询的句子的上下文含义和目的。

换句话说,Google搜索现在将能够更清楚地了解查询中一串单词的上下文。这意味着用户可以越来越多地搜索感觉自然,谷歌将能够更准确地理解和响应搜索查询。

在他的博客帖子中,谷歌的Nayak使用这个例子:“2019 Brazil traveler to USA needs a Visa。” Nayak指出,“to”这个词及其与其余查询的关系对于了解查询的含义至关重要。这是关于一个前往美国的巴西旅行而不是其他意思。它对官方旅行证件相关,而非对信用卡的需求有关。

Nayak指出,过去的谷歌算法的过去版本将无法使用“to”这个词来接受查询上下文的重要性。因此,使用旧算法,Google可能实际上可以返回关于前往巴西的美国公民的结果列表,而不是想要的展示方式。通过BERT,Google现在能够掌握这种级别的细节 – 使用“to”单词作为限定符 – 并返回查询的更相关的结果。

凭借其对上下文细微差别的新方法,BERT算法改变了SEO的策略,以及SEO的日常惯例,减少了关键字和关键字基于短语的SEO的权重值。关键词和短语在对竞争SEO排名的战略方向和理解方面仍然重要,因为它涉及高级内容策略和内容营销。但是,在改善排名方面,SEO的关键字分析方法现在具有较少的价值和影响。

了解这一变化的影响对于寻求前进的成功至关重要。这是因为BERT了解句子级别的搜索查询的上下文,包括Word Order和同义词。在BERT之前,谷歌依靠精确的关键字和关键字短语关联,以确定搜索排名和相关性。

BERT如何改变SEO策略?

要重申一个关键点,BERT将实心SEO策略的主要焦点从关注关键字和关键字短语的关注转移到主题的关键词。更广泛地关注关于搜索查询的主题相关性。

以下是您应该开始做的一些事情 – 或者应该停止执行 – 解决BERT算法的变化。

1、停止使用低质量的外包内容开发资源。现在,使用外包内容,写出的内容具有很少的知识或专业知识现在将损害您的SEO排名。这是因为搜索引擎不是基于关键字来排名,BERT现在考虑专业知识,权威和信任作为其核心资格排名因素。

2、制定主题重点的资源清单。正式确定您的主题重点,或将来将在未来。这就是:为什么:中小企业更有可能在会话语言中使用相关的行业行业行业和相关的同义词和短语。 BERT能够拿起这种级别的上下文协会,因为它与主题专业知识和权威有关。结果随着时间的推移将是更高且更有利的排名。

3、内容的质量与数量相比。在以前很长时间,内容营销人员已经不断通过更新内容来改善排名。内容新鲜度仍然重要,但现在,内容深度和质量问题超过发布一致性和更新。

BERT会改变我的搜索排名吗?

希望您现在有更好的掌握,现在BERT算法对SEO的当前状态和未来以及整体搜索排名的影响。下一个问题显然是“BERT改变了我在搜索中看到的结果?”

没有真正的“是”或“不”的方式来回答这个问题。真实的反应是“取决于”。

如果您只使用基于关键字的SEO,随着BERT算法的引入就更变旧的游戏规则。原本排名不错的公司突然大幅度下降。 (您正在监控您的搜索结果相对竞争对手的排名,不是吗?)

我该怎么SEO?

正如我之前提到的那样,这个问题的答案是“这取决于”。无论您的内容开发计划在哪个阶段,它可能会出现完善的速度。幸运的是,谷歌为我们提供了一些关于如何继续的指导。

让我们圈回电子邮件的E-A-T(专业知识,权威,值得信赖性)Litmus测试,以便在这篇文章中提到的内容。 E-A-T参考谷歌认为对网上合格内容的分类非常重要的三个战略内容柱。

“e”代表专业知识。如果您尚未使用中小企业作为您的内容开发的基石,则需要首先开始这样做。例如,在基于技术的公司中,中小企业可以是开发人员,程序员或产品经理。 “但我公司中的这些类型的人不是作家!”你可能会说。或者,“我们的开发人员没有时间编写2000字的博客帖子关于系统工程机器专有代码的重要性。”

请记住,搜索中的新标准并不是您内容的单词的方式,但它对有多权威和相关性。您的中小企业将适合BERT算法,以便完美地符合Google对内容的基线测试。

所以不是要求这些人自己写作,采访他们并记录谈话。如果他们是大多数中小企业,他们可以轻松地在与您的15分钟对话中生成2,000字的会话风格的博客文章。通过这种方法(关于主题的录制对话),您可以获得相关行业的行业术语,细微差别和上下文情绪,这将符合这个新的搜索时代内容。拍摄专家的访谈并转化为博客文章或新闻稿等。

只需这一步,您不仅处理了专业知识因素,而且通过采访贵公司或行业的权威者,您也在变得更有行业权威,以及符合E-A-T 内容策略。

通过在BERT算法的新时代应用E-A-T方法,您将在途中提高搜索排名,并在您网站的流量增加,而不是您思考的时间。

作者 east
深度学习 3月 29,2022

什么是Google BERT如何对它进行优化

听说过 Google 的新更新 BERT?如果您对搜索引擎优化 (SEO) 很感兴趣,您可能会拥有。在 SEO 世界中对 Google BERT 的炒作是有道理的,因为 BERT 使搜索更多地关注单词背后的语义或含义,而不是单词本身。

换句话说,搜索意图比以往任何时候都更加重要。谷歌最近更新的 BERT 影响了 SEO 世界,影响了十分之一的搜索查询,谷歌预计随着时间的推移,这将随着更多的语言和地区而增加。由于 BERT 将对搜索产生巨大影响,因此拥有高质量的内容比以往任何时候都更加重要。

为了使您的内容能够为 BERT(和搜索意图)发挥最佳效果,在本文中,我们将介绍 BERT 如何与搜索一起工作,以及如何使用 BERT 为您的网站带来更多流量。想与 SEO 专家交谈?与 WebFX 连接!

什么是 BERT?
BERT 代表来自 Transformers 的双向编码器表示。现在,这是一个包含一些非常技术性的机器学习术语的术语!

这是什么意思:

双向:BERT 同时对两个方向的句子进行编码
编码器表示:BERT 将句子翻译成它可以理解的词义表示
Transformers:允许 BERT 使用相对位置对句子中的每个单词进行编码,因为上下文在很大程度上取决于单词顺序(这是一种比准确记住句子如何输入框架更有效的方法)
如果你要改写它,你可以说 BERT 使用转换器来编码目标单词两侧的单词表示。从根本上说,BERT 是一个全新的、从未实现过的、最先进的自然语言处理 (NLP) 算法框架。这种类型的结构为谷歌的人工智能增加了一层机器学习,旨在更好地理解人类语言。

换句话说,通过这次新的更新,谷歌的人工智能算法可以以比以往更高水平的人类语境理解和常识来阅读句子和查询。虽然它对语言的理解程度不如人类,但它仍然是 NLP 在机器语言理解方面向前迈出的一大步。

BERT 不是什么
Google BERT 不会像之前的算法更新(如 Penguin 或 Panda)那样改变网页的判断方式。它不会将页面评为正面或负面。相反,它改进了对话式搜索查询中的搜索结果,因此结果更好地匹配其背后的意图。

BERT 历史
BERT 的存在时间比几个月前推出的 BIG 更新要长。自 2018 年 10 月发表研究论文 BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding 以来,自然学习处理 (NLP) 和机器学习 (ML) 社区一直在讨论它。不久之后,Google 发布了一个突破性的开源 NLP 框架,该框架基于 NLP 社区可以用来研究 NLP 并将其整合到他们的项目中的论文。

从那以后,出现了几个基于或合并了 BERT 的新 NLP 框架,包括谷歌和丰田的组合 ALBERT、Facebook 的 RoBERTa、微软的 MT-DNN 和 IBM 的 BERT-mtl。 BERT 在 NLP 社区引起的波澜占互联网上的大部分提及,但 BERT 在 SEO 世界中的提及正在获得牵引力。这是因为 BERT 专注于长尾查询中的语言以及像人类一样阅读网站,以便为搜索查询提供更好的结果。

BERT 是如何工作的?
Google BERT 是一个非常复杂的框架,理解它需要多年研究 NLP 理论和过程。搜索引擎优化世界不需要那么深入,但了解它在做什么以及为什么对于理解它将如何影响搜索结果从现在开始很有用。

因此,以下是 Google BERT 的工作原理:

谷歌 BERT 解释
以下是 BERT 如何从整体上查看句子或搜索查询的上下文:

BERT 接受查询
逐字逐句分解
查看单词之间所有可能的关系
构建一个双向地图,概述两个方向上的单词之间的关系
当单词彼此配对时,分析单词背后的上下文含义。
好的,为了更好地理解这一点,我们将使用以下示例:

每行代表“pandas”的含义如何改变句子中其他单词的含义,反之亦然。 关系是双向的,所以箭头是双向的。 当然,这是 BERT 如何看待上下文的一个非常非常简单的例子。

这个例子只检查我们的目标词“pandas ”和句子中其他有意义的片段之间的关系。 然而,BERT 分析句子中所有单词的上下文关系。 这张图可能更准确一点:

BERT 的类比
BERT 使用 Encoders 和 Decoders 来分析单词之间的关系。想象一下 BERT 如何作为翻译过程发挥作用,提供了一个很好的例子来说明它是如何工作的。您从输入开始,无论您想翻译成另一种语言的任何句子。

假设您想将上面的熊猫句子从英语翻译成韩语。不过,BERT 不懂英语或韩语,所以它使用编码器来翻译“熊猫除了竹子还吃什么?”变成它确实理解的语言。这种语言是它在分析语言的过程中为自己构建的语言(这是编码器表示的来源)。

BERT 根据单词的相对位置和对句子含义的重要性来标记单词。然后它将它们映射到一个抽象向量上,从而创建一种想象的语言。因此,BERT 将我们的英语句子转换为其想象的语言,然后使用解码器将想象的语言转换为韩语。

该过程非常适合翻译,但它也提高了任何基于 BERT 的 NLP 模型正确解析语言歧义的能力,例如:

代词参考
同义词和同音词
或具有多个定义的单词,例如“运行”
BERT 经过预训练
BERT 是经过预训练的,这意味着它有很多学习内容。但是使 BERT 与以前的 NLP 框架不同的一件事是 BERT 是在纯文本上进行预训练的。其他 NLP 框架需要一个由语言学家精心标记句法的单词数据库来理解单词。

语言学家必须将数据库中的每个单词标记为词性。这是一个严格而苛刻的过程,可能会在语言学家之间引发冗长的激烈辩论。词性可能很棘手,尤其是当词性由于句子中的其他单词而发生变化时。

BERT 自己做这件事,而且它是在无人监督的情况下做的,这使它成为世界上第一个这样做的 NLP 框架。它是使用维基百科训练的。那是超过 25 亿字!

BERT 可能并不总是准确的,但它分析的数据库越多,它的准确度就会越高。

BERT 是双向的
BERT 对句子进行双向编码。 简而言之,BERT 在一个句子中取一个目标词,并在任一方向查看围绕它的所有词。 BERT 的深度双向编码器在 NLP 框架中是独一无二的。

早期的 NLP 框架(例如 OpenAI GPT)仅在一个方向上对句子进行编码,在 OpenAI GPT 的情况下是从左到右。 后来的模型(如 ELMo)可以在目标词的左侧和右侧进行训练,但这些模型独立地连接编码。 这会导致目标词的每一侧之间的上下文断开。

另一方面,BERT 识别目标单词两侧所有单词的上下文,并且同时完成所有操作。 这意味着它可以完全看到和理解单词的含义如何影响整个句子的上下文。

单词如何相互关联(意味着它们一起出现的频率)是语言学家所说的搭配。

搭配词是经常一起出现的词——例如,“圣诞节”和“礼物”经常出现在每个词的几个词中。能够识别搭配有助于确定单词的含义。在我们之前的示例图像中,“trunk”可以有多种含义:

  • the main woody stem of a tree
  • the torso of a person or animal
  • a large box for holding travel items
  • the prehensile nose of an elephant
  • the storage compartment of a vehicle.

树的主要木质茎
人或动物的躯干
一个装旅行用品的大盒子
大象的鼻子
车辆的储藏室。
确定这句话中所用单词含义的唯一方法是查看周围的搭配。 “低音炮”通常与“汽车”一起出现,“后备箱”也是如此,因此根据上下文,“车辆储物箱”的定义可能是正确的答案。这正是 BERT 在查看句子时所做的。

它通过使用从预训练中学到的单词搭配来识别句子中每个单词的上下文。如果 BERT 单向阅读句子,则可能会错过识别低音炮和后备箱之间“汽车”的共享搭配。双向和整体查看句子的能力解决了这个问题。

BERT 使用变压器
BERT 的双向编码功能与转换器,这是有道理的。如果您还记得,BERT 中的“T”代表变压器。谷歌认为 BERT 是他们在变压器研究方面取得突破的结果。

谷歌将转换器定义为“处理与句子中所有其他单词相关的单词的模型,而不是按顺序一个接一个地处理。” Transformers 使用 Encoders 和 Decoders 来处理句子中单词之间的关系。 BERT 提取句子的每个单词,并赋予它单词含义的表示。每个单词的含义相互关联的强度由线条的饱和度来表示。

在下图的情况下,在左侧,“它”与“the”和“animal”的联系最紧密,在这种情况下识别“it”指的是什么。在右边,“it”与“street”的联系最为紧密。像这样的代词引用曾经是语言模型难以解决的主要问题之一,但 BERT 可以做到这一点

self attention diagram

来源 如果您是 NLP 爱好者,想知道什么是转换器及其工作原理背后的细节,您可以观看这段基于开创性文章的视频:Attention Is All You Need。

它们是一个很棒的视频和一篇优秀的论文(但老实说,它直接在我脑海中浮现)。对于我们其他麻瓜,BERT 背后的转换器的技术效果转化为更新,谷歌搜索可以更好地理解搜索结果背后的上下文,也就是用户意图。

BERT 使用掩码语言模型 (MLM)
BERT 的训练包括使用 Masked Language Modeling 预测句子中的单词。它的作用是掩盖句子中 15% 的单词,如下所示:

What do [MASK] eat other than bamboo?


然后,BERT 必须预测被掩码的词是什么。这做了两件事:它在单词上下文中训练 BERT,它提供了一种衡量 BERT 学习量的方法。被屏蔽的词阻止 BERT 学习复制和粘贴输入。

其他参数,例如向右移动解码器、下一个句子预测或回答上下文,有时是无法回答的问题也可以这样做。 BERT 提供的输出将表明 BERT 正在学习和实施其关于单词​​上下文的知识。

BERT 有什么影响?
这对搜索意味着什么?像 BERT 那样使用转换器双向映射查询尤为重要。

这意味着算法正在考虑诸如介词之类的单词背后的细微但有意义的细微差别,这些细微差别可能会极大地改变查询背后的意图。以这两个不同的搜索页面结果为例。我们将继续我们早期的熊猫和竹子主题。

关键字是:What do pandas eat other than bamboo

google search what do pandas eat other than bamboo

Panda bamboo

google search panda bamboo

请注意结果页面非常相似?几乎一半的有机结果是相同的,人们也问 (PAA) 部分有一些非常相似的问题。但是,搜索意图非常不同。

“熊猫竹”的范围很广,所以很难确定其意图,但它可能在想熊猫的竹子饮食。搜索页面非常好。另一方面,“熊猫除了竹子还吃什么”的搜索意图非常具体,搜索页面上的结果完全错过了。

唯一接近达到意图的结果可能有两个 PAA 问题:

大熊猫吃什么肉?
只吃竹子的大熊猫如何生存?
可以说是 Quora 的两个问题,其中一个很有趣:

可以训练熊猫吃竹子以外的食物吗?
熊猫吃人吗?
苗条的采摘,确实。在此搜索查询中,“其他”一词在搜索意图的含义中起着重要作用。在 BERT 更新之前,Google 的算法在返回信息时会定期忽略诸如“other than”之类的功能/填充词。

这导致搜索页面无法匹配像这样的搜索意图。由于 BERT 仅影响 10% 的搜索查询,因此在撰写本文时左侧页面并未受到 BERT 的影响也就不足为奇了。 Google 在其 BERT 解释页面上提供的这个示例显示了 BERT 如何影响搜索结果:

can you get medicine for someone pharmacy before and after

精选片段
BERT 将产生的最重要影响之一将是精选片段。精选片段是有机的,并且依赖于机器学习算法,而 BERT 完全符合要求。精选片段结果最常从第一个搜索结果页面中提取,但现在可能会有一些例外。

因为它们是有机的,很多因素都可以使它们发生变化,包括像 BERT 这样的新算法更新。使用 BERT,影响精选片段的算法可以更好地分析搜索查询背后的意图,并更好地将搜索结果与它们匹配。 BERT 也很可能能够获取冗长的结果文本,找到核心概念,并将内容总结为特色片段。

国际搜索
由于语言具有相似的基本语法规则,BERT 可以提高翻译的准确性。 BERT 每次学习翻译一种新语言时,都会获得新的语言技能。这些技能可以转移并帮助 BERT 翻译它从未见过的更高精度的语言。

如何针对 BERT 优化我的网站?
现在我们遇到一个大问题:如何针对 Google BERT 进行优化?简短的回答?

你不能。 BERT 是一个人工智能框架。它利用它获得的每一条新信息进行学习。

它处理信息和做出决策的速度意味着即使是 BERT 的开发人员也无法预测 BERT 将做出的选择。很可能,BERT 甚至不知道它为什么会做出这样的决定。如果它不知道,那么 SEO 就无法直接针对它进行优化。

但是,您可以在搜索页面中进行排名的方法是继续生成符合搜索意图的人性化内容。 BERT 的目的是帮助 Google 了解用户意图,因此针对用户意图进行优化将针对 BERT 进行优化。

所以,做你一直在做的事情。
研究你的目标关键词。
关注用户并生成他们想要看到的内容。
最终,当你写内容时,问问自己:

我的读者能否在我的内容中找到他们正在寻找的内容?

作者 east
深度学习 3月 27,2022

什么是BERT模型和作用?

Google 最近进行了一项重要的算法更新,称为 Google BERT,以更好地理解搜索并为更自然的语言查询生成结果。算法更新还将为他们的人工智能技术提供自然语言和搜索上下文。每天数十亿次的搜索将有助于增强 Google 的 AI 功能,从而改善搜索结果、提高对语音搜索的理解,并帮助 Google 更好地了解消费者行为。

向 Google BERT 打个招呼!

BERT 是谷歌自 2015 年推出 RankBrain 以来最大的搜索算法。事实上,谷歌表示这次更新代表了“过去五年来最大的飞跃,也是搜索领域最大的飞跃之一。” BERT 通过了解用户在更具会话结构的查询中的意图,使搜索更加集中。

让我们更好地了解 BERT,并了解它如何帮助优化您的搜索。

什么是 BERT?
BERT 是一种人工智能 (AI) 系统,代表 Transformers 的双向编码器表示。这种搜索进步是谷歌对转换器研究的结果,转换器是处理与句子中所有其他单词相关的单词的模型,而不是按顺序一个接一个地处理。简而言之,此更新侧重于短语而不是简单的单词。

在排名结果方面,BERT 将影响十分之一的搜索查询。此算法更新也被应用于帮助为世界各地的人们提供更好的搜索。通过从一种语言中学习,相关结果可以应用于许多其他语言。 Google 正在许多国家/地区使用 BERT 模型来改进片段,支持韩语、印地语和葡萄牙语等 70 多种语言。

BERT+
然而,BERT 不仅仅是一种搜索算法。它也是一个机器学习自然语言处理框架、一个不断发展的计算效率工具,以及一个开源研究项目和学术论文,于 2018 年 10 月首次发表,名称为 BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding。

怎么运作
BERT 的美妙之处在于,无论单词的拼写方式或它们在查询中的顺序,它都能计算出您的搜索并显示相关信息。 BERT 能够基于句子中的整个单词集而不是传统的单词序列来训练语言模型,例如从左到右或从左到右和从右到左的组合。谷歌现在可以解决由许多具有多种含义的单词组成的模棱两可的短语。

此外,日常语言中存在细微差别,计算机并不完全理解人类的行为方式。因此,当搜索包含一个短语时,BERT 将解释它并根据句子的创建方式和发音给出结果。这很重要,因为即使是最简单的短语与单数单词相比也可能具有完全不同的含义。例如,在“纽约到洛杉矶”和“四分之一到九点”这样的短语中,“到”这个词有不同的含义,这可能会导致搜索引擎混淆。 BERT 区分这些细微差别以促进更相关的搜索。

RankBrain 仍在努力
RankBrain 是谷歌第一个用于理解查询的人工智能方法。它同时查看搜索和谷歌索引中的网页内容,以更好地理解单词的含义。 BERT 不会取代 RankBrain,它是更好地理解内容、自然语言和查询的扩展。 RankBrain 仍将被使用,但当 Google 认为在 BERT 的帮助下更适合查询时,搜索将使用新模型。似乎这句谚语是真的……两种搜索算法比一种更好!

更智能的搜索结果
作为谷歌最新的算法更新,BERT 通过更好地理解自然语言来影响搜索,尤其是在会话短语中。 BERT 将影响大约 10% 的查询以及自然排名和精选片段。所以这对谷歌……和我们所有人来说都是一件大事。有这么多问题,找到与我们的“正常”短语查询匹配的相关结果肯定会让我们的搜索体验更加轻松。搜索愉快!

作者 east
深度学习 3月 27,2022

深入了解 BERT 模型的代码-分解 Hugging Face Bert 实现

已经有很多关于如何从头开始创建简化的 Bert 模型及其工作原理的教程。 在本文中,我们将做一些稍微不同的事情——我们通过 BERT 的实际 Hugging face 实现分解其所有组件。


介绍
在过去的几年里,Transformer 模型彻底改变了 NLP 领域。 BERT (Bidirectional Encoder Representations from Transformers) 是最成功的 Transformer 之一——由于与 LSTM 的递归结构不同,通过注意力机制和训练时间更好地理解了上下文,它在性能上都优于以前的 SOTA 模型(如 LSTM), BERT 是可并行的。
现在不用再等了,让我们深入研究代码,看看它是如何工作的。 首先我们加载 Bert 模型并输出 BertModel 架构:

# with bertviz package we can output attentions and hidden states 
from bertviz.transformers_neuron_view import BertModel, BertConfig
from transformers import BertTokenizer

max_length = 256
config = BertConfig.from_pretrained("bert-base-cased", output_attentions=True, output_hidden_states=True, return_dict=True)
tokenizer = BertTokenizer.from_pretrained("bert-base-cased")
config.max_position_embeddings = max_length

model = BertModel(config)
model = model.eval()

display(model)
# output : 

BertModel(
  (embeddings): BertEmbeddings(
    (word_embeddings): Embedding(30522, 768, padding_idx=0)
    (position_embeddings): Embedding(256, 768)
    (token_type_embeddings): Embedding(2, 768)
    (LayerNorm): BertLayerNorm()
    (dropout): Dropout(p=0.1, inplace=False)
  )
  (encoder): BertEncoder(
    (layer): ModuleList(
      (0): BertLayer(
        (attention): BertAttention(
          (self): BertSelfAttention(
            (query): Linear(in_features=768, out_features=768, bias=True)
            (key): Linear(in_features=768, out_features=768, bias=True)
            (value): Linear(in_features=768, out_features=768, bias=True)
            (dropout): Dropout(p=0.1, inplace=False)
          )
          (output): BertSelfOutput(
            (dense): Linear(in_features=768, out_features=768, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1, inplace=False)
          )
        )
        (intermediate): BertIntermediate(
          (dense): Linear(in_features=768, out_features=3072, bias=True)
        )
        (output): BertOutput(
          (dense): Linear(in_features=3072, out_features=768, bias=True)
          (LayerNorm): BertLayerNorm()
          (dropout): Dropout(p=0.1, inplace=False)
        )
      )
      (1): BertLayer(
        (attention): BertAttention(
          (self): BertSelfAttention(
            (query): Linear(in_features=768, out_features=768, bias=True)
            (key): Linear(in_features=768, out_features=768, bias=True)
            (value): Linear(in_features=768, out_features=768, bias=True)
            (dropout): Dropout(p=0.1, inplace=False)
          )
          (output): BertSelfOutput(
            (dense): Linear(in_features=768, out_features=768, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1, inplace=False)
          )
        )
        (intermediate): BertIntermediate(
          (dense): Linear(in_features=768, out_features=3072, bias=True)
        )
        (output): BertOutput(
          (dense): Linear(in_features=3072, out_features=768, bias=True)
          (LayerNorm): BertLayerNorm()
          (dropout): Dropout(p=0.1, inplace=False)
        )
      )
      
      ......

      (11): BertLayer(
        (attention): BertAttention(
          (self): BertSelfAttention(
            (query): Linear(in_features=768, out_features=768, bias=True)
            (key): Linear(in_features=768, out_features=768, bias=True)
            (value): Linear(in_features=768, out_features=768, bias=True)
            (dropout): Dropout(p=0.1, inplace=False)
          )
          (output): BertSelfOutput(
            (dense): Linear(in_features=768, out_features=768, bias=True)
            (LayerNorm): BertLayerNorm()
            (dropout): Dropout(p=0.1, inplace=False)
          )
        )
        (intermediate): BertIntermediate(
          (dense): Linear(in_features=768, out_features=3072, bias=True)
        )
        (output): BertOutput(
          (dense): Linear(in_features=3072, out_features=768, bias=True)
          (LayerNorm): BertLayerNorm()
          (dropout): Dropout(p=0.1, inplace=False)
        )
      )
    )
  )
  (pooler): BertPooler(
    (dense): Linear(in_features=768, out_features=768, bias=True)
    (activation): Tanh()
  )
)

我们分别分析了 3 个部分:Embeddings、具有 12 个重复 Bert 层的 Encoder 和 Pooler。 最终我们将添加一个分类层。
伯特嵌入:
从原始文本开始,首先要做的是将我们的句子拆分为标记,然后我们可以将其传递给 BertEmbeddings。 我们使用基于 WordPiece 的 BertTokenizer——子词标记化可训练算法,有助于平衡词汇量和词汇量外的单词。 看不见的词被分成子词,这些子词是在分词器的训练阶段派生的(这里有更多详细信息)。 现在让我们从 20newsgroups 数据集中导入几个句子并标记它们

from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train')
inputs_tests = tokenizer(newsgroups_train['data'][:3], truncation=True, padding=True, max_length=max_length, return_tensors='pt')

一旦句子被分割成标记,我们就会为每个标记分配一个具有代表性的数字向量,该向量在 n 维空间中表示该标记。每个维度都包含该单词的一些信息,因此如果我们假设特征是 Wealth、Gender、Cuddly,则模型在训练嵌入层之后,将使用以下 3 维向量表示例如单词 king:(0.98, 1, 0.01)和 cat (0.02, 0.5, 1)。然后我们可以使用这些向量来计算单词之间的相似度(使用余弦距离)并做许多其他事情。
注意:实际上,我们无法得出这些特征名称的真正含义,但以这种方式思考它们有助于获得更清晰的画面。
所以 word_embeddings 在这种情况下是一个形状矩阵 (30522, 768),其中第一个维度是词汇维度,而第二个维度是嵌入维度,即我们用来表示一个单词的特征的数量。对于 base-bert,它是 768,对于更大的型号,它会增加。一般来说,嵌入维度越高,我们可以更好地表示某些单词——这在一定程度上是正确的,在某些时候增加维度不会大大提高模型的准确性,而计算复杂度却可以。

model.embeddings.word_embeddings.weight.shape
output: torch.Size([30522, 768])

需要 position_embeddings 是因为,与 LSTM 模型不同,例如 LSTM 模型顺序处理令牌,因此通过构造具有每个令牌的顺序信息,Bert 模型并行处理令牌并合并每个令牌的位置信息,我们需要从 position_embeddings 矩阵添加此信息 . 它的形状是 (256, 768),其中前者表示最大句子长度,而后者是词嵌入的特征维度——因此根据每个标记的位置,我们检索相关向量。 在这种情况下,我们可以看到这个矩阵是学习的,但还有其他实现是使用正弦和余弦构建的。

model.embeddings.position_embeddings.weight.shapeoutput: torch.Size([256, 768])

token_type_embeddings 在这里是“冗余的”,来自 Bert 训练任务,其中评估了两个句子之间的语义相似性——需要这种嵌入来区分第一句和第二句。 我们不需要它,因为我们只有一个用于分类任务的输入句子。
一旦我们为句子中的每个单词提取单词嵌入、位置嵌入和类型嵌入,我们只需将它们相加即可得到完整的句子嵌入。 所以对于第一句话,它将是:

f1 = torch.index_select(model.embeddings.word_embeddings.weight, 0, inputs_tests['input_ids'][0])  # words embeddings
  + torch.index_select(model.embeddings.position_embeddings.weight, 0, torch.tensor(range(inputs_tests['input_ids'][0].size(0))).long()) \ # pos embeddings
 + torch.index_select(model.embeddings.token_type_embeddings.weight, 0, inputs_tests['token_type_ids'][0]) # token embeddings

对于我们的 3 个句子的 mini-batch,我们可以通过以下方式获取它们:

n_batch = 3
shape_embs = (inputs_tests['input_ids'].shape) + (model.embeddings.word_embeddings.weight.shape[1], )
w_embs_batch = torch.index_select(model.embeddings.word_embeddings.weight, 0, inputs_tests['input_ids'].reshape(1,-1).squeeze(0)).reshape(shape_embs)
pos_embs_batch = torch.index_select(model.embeddings.position_embeddings.weight, 0, 
                                    torch.tensor(range(inputs_tests['input_ids'][1].size(0))).repeat(1, n_batch).squeeze(0)).reshape(shape_embs)
type_embs_batch = torch.index_select(model.embeddings.token_type_embeddings.weight, 0, 
                                     inputs_tests['token_type_ids'].reshape(1,-1).squeeze(0)).reshape(shape_embs)
batch_all_embs = w_embs_batch + pos_embs_batch + type_embs_batch
batch_all_embs.shape # (batch_size, n_words, embedding dim)

接下来我们有一个 LayerNorm 步骤,它可以帮助模型更快地训练和更好地泛化。 我们通过令牌的均值嵌入和标准差对每个令牌的嵌入进行标准化,使其具有零均值和单位方差。 然后,我们应用经过训练的权重和偏差向量,以便可以将其转换为具有不同的均值和方差,以便训练期间的模型可以自动适应。 因为我们独立于其他示例计算不同示例的均值和标准差,所以它与批量归一化不同,后者的归一化是跨批次维度的,因此取决于批次中的其他示例。

# single example normalization
ex1 = f1[0, :]
ex1_mean = ex1.mean()
ex1_std = (ex1 - ex1_mean).pow(2).mean()
norm_example = ((ex1- ex1_mean)/torch.sqrt(ex1_std + 1e-12))
norm_example_centered = model.embeddings.LayerNorm.weight * norm_example + model.embeddings.LayerNorm.bias


def layer_norm(x, w, b):
    mean_x = x.mean(-1, keepdim=True)
    std_x = (x - mean_x).pow(2).mean(-1, keepdim=True)
    x_std = (x - mean_x) / torch.sqrt(std_x + 1e-12)
    shifted_x = w * x_std + b
    return shifted_x
  
# batch normalization
norm_embs = layer_norm(batch_all_embs, model.embeddings.LayerNorm.weight, model.embeddings.LayerNorm.bias

让我们最后应用 Dropout,我们用零替换一些具有一定 dropout 概率的值。 Dropout 有助于减少过度拟合,因为我们随机阻止来自某些神经元的信号,因此网络需要找到其他路径来减少损失函数,因此它学会了如何更好地泛化而不是依赖某些路径。 我们还可以将 dropout 视为一种模型集成技术,因为在每一步的训练过程中,我们随机停用某些神经元,最终形成“不同”的网络,最终在评估期间集成这些神经元。
注意:因为我们将模型设置为评估模式,我们将忽略所有的 dropout 层,它们仅在训练期间使用。 为了完整起见,我们仍将其包括在内。

norm_embs_dropout = model.embeddings.dropout(norm_embs)

我们可以检查我们是否获得了与模型相同的结果:

embs_model = model.embeddings(inputs_tests[‘input_ids’], inputs_tests[‘token_type_ids’])
torch.allclose(embs_model, norm_embs, atol=1e-06) # True

编码器
编码器是最神奇的地方。有 12 个 BertLayers,前一个的输出被馈送到下一个。这是使用注意力来创建与上下文相关的原始嵌入的不同表示的地方。在 BertLayer 中,我们首先尝试理解 BertAttention——在导出每个单词的嵌入之后,Bert 使用 3 个矩阵——Key、Query 和 Value,来计算注意力分数,并根据句子中的其他单词导出单词嵌入的新值;通过这种方式,Bert 是上下文感知的,每个单词的嵌入而不是固定的,上下文独立是基于句子中的其他单词推导出来的,并且在为某个单词推导新嵌入时其他单词的重要性由注意力分数表示。为了导出每个单词的查询和键向量,我们需要将其嵌入乘以经过训练的矩阵(查询和键是分开的)。例如,要导出第一句的第一个词的查询向量:

att_head_size = int(model.config.hidden_size/model.config.num_attention_heads)
n_att_heads = model.config.num_attention_heads
norm_embs[0][0, :] @ model.encoder.layer[0].attention.self.query.weight.T[:, :att_head_size] + \
                      model.encoder.layer[0].attention.self.query.bias[:att_head_size]

我们可以注意到,在整个查询和关键矩阵中,我们只选择了前 64 个 (=att_head_size) 列(原因将在稍后说明)——这是转换后单词的新嵌入维度,它小于原始嵌入 维度 768。这样做是为了减少计算负担,但实际上更长的嵌入可能会带来更好的性能。 实际上,这是降低复杂性和提高性能之间的权衡。
现在我们可以推导出整个句子的 Query 和 Key 矩阵:

Q_first_head = norm_embs[0] @ model.encoder.layer[0].attention.self.query.weight.T[:, :att_head_size] + \
               model.encoder.layer[0].attention.self.query.bias[:att_head_size] 
K_first_head = norm_embs[0] @ model.encoder.layer[0].attention.self.key.weight.T[:, :att_head_size] + \
               model.encoder.layer[0].attention.self.key.bias[:att_head_size]

为了计算注意力分数,我们将 Query 矩阵乘以 Key 矩阵,并将其标准化为新嵌入维度的平方根 (=64=att_head_size)。 我们还添加了一个修改后的注意力掩码。 初始注意掩码 (inputs[‘attention_mask’][0]) 是一个 1 和 0 的张量,其中 1 表示该位置有一个标记,0 表示它是一个填充标记。
如果我们从 1 中减去注意力掩码并将其乘以一个高负数,当我们应用 SoftMax 时,我们实际上将那些负值发送到零,然后根据其他值推导出概率。 让我们看下面的例子:
如果我们有一个 3 个标记 + 2 个填充的句子,我们会得到以下注意力掩码:[0,0,0, -10000, -10000]
让我们应用 SoftMax 函数:

torch.nn.functional.softmax(torch.tensor([0,0,0, -10000, -10000]).float())# tensor([0.3333, 0.3333, 0.3333, 0.0000, 0.0000])mod_attention = (1.0 – inputs[‘attention_mask’][[0]]) * -10000.0attention_scores = torch.nn.Softmax(dim=-1)((Q_first_head @ K_first_head.T)/ math.sqrt(att_head_size) + mod_attention)

让我们检查一下我们得到的注意力分数是否与我们从模型中得到的相同。 我们可以使用以下代码从模型中获取注意力分数:

as we defined output_attentions=True, output_hidden_states=True, return_dict=True we will get last_hidden_state, pooler_output, hidden_states for each layer and attentions for each layer
out_view = model(**inputs_tests)

out_view 包含:
last_hidden_state (batch_size, sequence_length, hidden_size) : 最后一个 BertLayer 输出的隐藏状态
pooler_output (batch_size, hidden_size) : Pooler 层的输出
hidden_states (batch_size, sequence_length, hidden_size):模型在每个 BertLayer 输出的隐藏状态加上初始嵌入
注意(batch_size、num_heads、sequence_length、sequence_length):每个 BertLayer 一个。 注意力 SoftMax 后的注意力权重

torch.allclose(attention_scores, out_view[-1][0][‘attn’][0, 0, :, :], atol=1e-06)) # True
print(attention_scores[0, :])
tensor([1.0590e-04, 2.1429e-03, .... , 4.8982e-05], grad_fn=<SliceBackward>)

注意分数矩阵的第一行表示,要为第一个标记创建新嵌入,我们需要注意权重 = 1.0590e-04 的第一个标记(对自身),权重 = 2.1429e-03 的第二个标记 等等。 换句话说,如果我们将这些分数乘以其他标记的向量嵌入,我们会得出第一个标记的新表示,但是,我们将使用下面计算的值矩阵,而不是实际使用嵌入。
值矩阵的推导方式与查询和键矩阵相同:

V_first_head = norm_embs[0] @ model.encoder.layer[0].attention.self.value.weight.T[:, :att_head_size] + \
              model.encoder.layer[0].attention.self.value.bias[:att_head_size]

然后我们将这些值乘以注意力分数以获得新的上下文感知词表示

new_embed_1 = (attention_scores @ V_first_head)

现在您可能想知道,为什么我们要从张量中选择前 64 个 (=att_head_size) 元素。 好吧,我们上面计算的是 Bert 注意力层的一个头,但实际上有 12 个。 这些注意力头中的每一个都会创建不同的单词表示(new_embed_1 矩阵),例如,给定以下句子“ I like to eat pizza in the Italian restaurants ”,在第一个头中,“pizza”一词可能主要关注前一个单词 ,单词本身以及后面的单词和剩余单词的注意力将接近于零。 在下一个头中,它可能会关注所有动词(like 和 eat),并以这种方式捕捉与第一个头不同的关系。
现在,我们可以以矩阵形式将它们一起推导,而不是单独推导每个头部:

Q = norm_embs @ model.encoder.layer[0].attention.self.query.weight.T + model.encoder.layer[0].attention.self.query.bias
K = norm_embs @ model.encoder.layer[0].attention.self.key.weight.T + model.encoder.layer[0].attention.self.key.bias
V = norm_embs @ model.encoder.layer[0].attention.self.value.weight.T + model.encoder.layer[0].attention.self.value.bias
new_x_shape = Q.size()[:-1] + (n_att_heads, att_head_size)
new_x_shape # torch.Size([3, 55, 12, 64])
Q_reshaped = Q.view(*new_x_shape)
K_reshaped = K.view(*new_x_shape)
V_reshaped = V.view(*new_x_shape)
att_scores = (Q_reshaped.permute(0, 2, 1, 3) @ K_reshaped.permute(0, 2, 1, 3).transpose(-1, -2))
att_scores = (att_scores/ math.sqrt(att_head_size)) + extended_attention_mask
attention_probs = torch.nn.Softmax(dim=-1)(att_scores)

第一个例子和第一个 head 的注意力和我们之前推导出的一样:

example = 0
head = 0
torch.allclose(attention_scores, attention_probs[example][head]) # True

我们现在将 12 个头的结果连接起来,并将它们传递给我们已经在嵌入部分中看到的一堆线性层、归一化层和 dropout,以获得第一层的编码器结果。

att_heads = []
for i in range(12):
  att_heads.append(attention_probs[0][i] @ V_reshaped[0, : , i, :])
output_dense = torch.cat(att_heads, 1) @ model.encoder.layer[0].attention.output.dense.weight.T + \
               model.encoder.layer[0].attention.output.dense.bias
output_layernorm = layer_norm(output_dense + norm_embs[0], 
                              model.encoder.layer[0].attention.output.LayerNorm.weight, 
                              model.encoder.layer[0].attention.output.LayerNorm.bias)
interm_dense = torch.nn.functional.gelu(output_layernorm @ model.encoder.layer[0].intermediate.dense.weight.T + \
                                        model.encoder.layer[0].intermediate.dense.bias)
out_dense = interm_dense @ model.encoder.layer[0].output.dense.weight.T + model.encoder.layer[0].output.dense.bias
out_layernorm  = layer_norm(out_dense + output_layernorm, 
                            model.encoder.layer[0].output.LayerNorm.weight, 
                            model.encoder.layer[0].output.LayerNorm.bias)

output_dense 我们只是通过线性层传递连接的注意力结果。然后我们需要进行归一化,但我们可以看到,我们不是立即对 output_dense 进行归一化,而是首先将其与我们的初始嵌入相加——这称为残差连接。当我们增加神经网络的深度时,即堆叠越来越多的层时,我们会遇到梯度消失/爆炸的问题,当梯度消失的情况下,模型无法再学习,因为传播的梯度接近于零初始层停止改变权重并改进。当权重因极端更新而最终爆炸(趋于无穷大)而无法稳定时,梯度爆炸的相反问题。现在,正确初始化权重和归一化有助于解决这个问题,但观察到的是,即使网络变得更加稳定,性能也会随着优化的困难而下降。添加这些残差连接有助于提高性能,即使我们不断增加深度,网络也变得更容易优化。 out_layernorm 中也使用了残差连接,它实际上是第一个 BertLayer 的输出。最后要注意的是,当我们计算 interterm_dense 时,在将 AttentionLayer 的输出传递到线性层之后,会应用非线性 GeLU 激活函数。 GeLU 表示为:

查看图表我们可以看到,如果由公式 max(input, 0) 给出的 ReLU 在正域中是单调的、凸的和线性的,那么 GeLU 在正域中是非单调的、非凸的和非线性的 正域,因此可以逼近更容易复杂的函数。

我们现在已经成功地复制了整个 BertLayer。 该层的输出(与初始嵌入的形状相同)进入下一个 BertLayer,依此类推。 总共有 12 个 BertLayers。 因此,将所有这些放在一起,我们可以从编码器中获得所有 3 个示例的最终结果:

n_batch = 3
tot_n_layers = 12
tot_n_heads = 12
shape_embs = (inputs_tests['input_ids'].shape) + (model.embeddings.word_embeddings.weight.shape[1], )
w_embs_batch = torch.index_select(model.embeddings.word_embeddings.weight, 
                                  0, inputs_tests['input_ids'].reshape(1,-1).squeeze(0)).reshape(shape_embs)
pos_embs_batch = torch.index_select(model.embeddings.position_embeddings.weight, 0, 
                                    torch.tensor(range(inputs_tests['input_ids'][1].size(0))).repeat(1, n_batch).squeeze(0)).reshape(shape_embs)
type_embs_batch = torch.index_select(model.embeddings.token_type_embeddings.weight, 0, 
                                     inputs_tests['token_type_ids'].reshape(1,-1).squeeze(0)).reshape(shape_embs)
batch_all_embs = w_embs_batch + pos_embs_batch + type_embs_batch
normalized_embs = layer_norm(batch_all_embs, model.embeddings.LayerNorm.weight, model.embeddings.LayerNorm.bias)
extended_attention_mask = inputs['attention_mask'].unsqueeze(1).unsqueeze(2)
extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0
for layer_n in range(tot_n_layers):
 if layer_n == 0:
   # compute Q, K and V matrices
   Q = normalized_embs @ model.encoder.layer[layer_n].attention.self.query.weight.T + \ 
                         model.encoder.layer[layer_n].attention.self.query.bias
   K = normalized_embs @ model.encoder.layer[layer_n].attention.self.key.weight.T + \
                         model.encoder.layer[layer_n].attention.self.key.bias
   V = normalized_embs @ model.encoder.layer[layer_n].attention.self.value.weight.T + \
                         model.encoder.layer[layer_n].attention.self.value.bias
   # reshape
   new_x_shape = Q.size()[:-1] + (n_att_heads, att_head_size)
   Q_reshaped = Q.view(*new_x_shape)
   K_reshaped = K.view(*new_x_shape)
   V_reshaped = V.view(*new_x_shape)
   # compute attention probabilities
   att_scores = (Q_reshaped.permute(0, 2, 1, 3) @ K_reshaped.permute(0, 2, 1, 3).transpose(-1, -2))
   att_scores = (att_scores/ math.sqrt(att_head_size)) + extended_attention_mask
   attention_probs = torch.nn.Softmax(dim=-1)(att_scores)
   # concatenate attention heads
   att_heads = []
   for i in range(tot_n_heads):
    att_heads.append(attention_probs[:, i] @ V_reshaped[:, : , i, :])

   output_dense = torch.cat(att_heads, 2) @ model.encoder.layer[layer_n].attention.output.dense.weight.T + \
                                            model.encoder.layer[layer_n].attention.output.dense.bias
   # normalization + residual connection
   output_layernorm = layer_norm(output_dense + normalized_embs, 
                                 model.encoder.layer[layer_n].attention.output.LayerNorm.weight,
                                 model.encoder.layer[layer_n].attention.output.LayerNorm.bias)
   # linear layer + non linear gelu activation
   interm_dense = torch.nn.functional.gelu(output_layernorm @ model.encoder.layer[layer_n].intermediate.dense.weight.T + \
                                           model.encoder.layer[layer_n].intermediate.dense.bias)
   # linear layer
   out_dense = interm_dense @ model.encoder.layer[layer_n].output.dense.weight.T + model.encoder.layer[layer_n].output.dense.bias
   # normalization + residual connection
   out_layernorm = layer_norm(out_dense + output_layernorm, 
                              model.encoder.layer[layer_n].output.LayerNorm.weight, 
                              model.encoder.layer[layer_n].output.LayerNorm.bias)
 else:
   # compute Q, K and V matrices
   Q = out_layernorm @ model.encoder.layer[layer_n].attention.self.query.weight.T + \
                              model.encoder.layer[layer_n].attention.self.query.bias
   K = out_layernorm @ model.encoder.layer[layer_n].attention.self.key.weight.T + \
                              model.encoder.layer[layer_n].attention.self.key.bias
   V = out_layernorm @ model.encoder.layer[layer_n].attention.self.value.weight.T + \
                              model.encoder.layer[layer_n].attention.self.value.bias
   # reshape
   Q_reshaped = Q.view(*new_x_shape)
   K_reshaped = K.view(*new_x_shape)
   V_reshaped = V.view(*new_x_shape)
   # compute attention probabilities
   att_scores = (Q_reshaped.permute(0, 2, 1, 3) @ K_reshaped.permute(0, 2, 1, 3).transpose(-1, -2))
   att_scores = (att_scores/ math.sqrt(att_head_size)) + extended_attention_mask
   attention_probs = torch.nn.Softmax(dim=-1)(att_scores)
   # concatenate attention heads
   att_heads = []
   for i in range(tot_n_heads):
    att_heads.append(attention_probs[:, i] @ V_reshaped[:, : , i, :])

   output_dense = torch.cat(att_heads, 2) @ model.encoder.layer[layer_n].attention.output.dense.weight.T + \
                                            model.encoder.layer[layer_n].attention.output.dense.bias
   # normalization + residual connection
   output_layernorm = layer_norm(output_dense + out_layernorm, 
                                 model.encoder.layer[layer_n].attention.output.LayerNorm.weight, 
                                 model.encoder.layer[layer_n].attention.output.LayerNorm.bias)

   # linear layer + non linear gelu activation
   interm_dense = torch.nn.functional.gelu(output_layernorm @ model.encoder.layer[layer_n].intermediate.dense.weight.T + \
                                                              model.encoder.layer[layer_n].intermediate.dense.bias)
   # linear layer
   out_dense = interm_dense @ model.encoder.layer[layer_n].output.dense.weight.T + model.encoder.layer[layer_n].output.dense.bias
   # normalization + residual connection
   out_layernorm = layer_norm(out_dense + output_layernorm, 
                              model.encoder.layer[layer_n].output.LayerNorm.weight, 
                              model.encoder.layer[layer_n].output.LayerNorm.bias)

注意 out_layernorm – 每层的输出如何被馈送到下一层。
我们可以看到这与 out_view 中的结果相同


torch.allclose(out_view[-2][-1], out_layernorm, atol=1e-05) # True


Pooler
现在我们可以获取最后一个 BertLayer 的第一个令牌输出,即 [CLS],将其通过一个线性层并应用一个 Tanh 激活函数来获得池化输出。使用第一个标记进行分类的原因来自于模型是如何被训练为 Bert state 的作者的:
每个序列的第一个标记始终是一个特殊的分类标记 ([CLS])。与该标记对应的最终隐藏状态用作分类任务的聚合序列表示。


out_pooler = torch.nn.functional.tanh(out_layernorm[:, 0] @ model.pooler.dense.weight.T + model.pooler.dense.bias)


分类器
最后,我们创建一个简单的类,它将是一个简单的线性层,但您可以向它添加一个 dropout 和其他东西。我们在这里假设一个二元分类问题(output_dim=2),但它可以是任何维度的。

from torch import nn
class Classifier(nn.Module):
    
    def __init__(self, output_dim=2):
        super(Classifier, self).__init__()
        self.classifier = nn.Linear(model.config.hidden_size, output_dim, bias=True)
    
    def forward(self, x):
        return self.classifier(x)
classif = Classifier()
classif(out_pooler)
tensor([[-0.2918, -0.5782],
        [ 0.2494, -0.1955],
        [ 0.1814,  0.3971]], grad_fn=<AddmmBackward>)

引用:

 
https://arxiv.org/pdf/1606.08415v3.pdf
https://arxiv.org/pdf/1810.04805.pdf
https://jalammar.github.io/illustrated-transformer/
https://github.com/huggingface/transformers/

作者 east
人工智能 3月 25,2022

google BERT开源网站介绍中文翻译

BERT
2020 年 3 月 11 日新:更小的 BERT 模型

这是在 Well-Read Students Learn Better: On the Importance of Pre-training Compact Models 中引用的 24 个较小的 BERT 模型(仅英文,不加大小写,使用 WordPiece 掩码训练)的版本。

我们已经证明,标准 BERT 配方(包括模型架构和训练目标)在各种模型大小上都有效,除了 BERT-Base 和 BERT-Large。较小的 BERT 模型适用于计算资源受限的环境。它们可以以与原始 BERT 模型相同的方式进行微调。然而,它们在知识提炼的背景下最为有效,其中微调标签由更大、更准确的教师生成。

我们的目标是在计算资源较少的机构中进行研究,并鼓励社区寻求创新方向来替代增加模型容量。

您可以从此处下载所有 24 个,也可以从下表中单独下载:

请注意,包含此版本中的 BERT-Base 模型只是为了完整性; 它在与原始模型相同的机制下进行了重新训练。

以下是测试集上对应的 GLUE 分数:

对于每个任务,我们从下面的列表中选择了最好的微调超参数,并训练了 4 个 epoch:

批量大小:8、16、32、64、128
学习率:3e-4、1e-4、5e-5、3e-5
如果您使用这些模型,请引用以下论文:

@article{turc2019,
标题={阅读良好的学生学得更好:关于预训练紧凑模型的重要性},
作者={Turc, Iulia and Chang, Ming-Wei and Lee, Kenton and Toutanova, Kristina},
journal={arXiv 预印本 arXiv:1908.08962v2 },
年={2019}
}
2019 年 5 月 31 日新:全词掩蔽模型

这是几个新模型的发布,这些模型是改进预处理代码的结果。

在原始的预处理代码中,我们随机选择 WordPiece 标记进行掩码。例如:

输入文本:这个人跳起来,把他的篮子放在 phil ##am ##mon 的头上 原始蒙面输入:[MASK] man [MASK] up , put his [MASK] on phil [MASK] ##mon ‘s头

这项新技术被称为全字掩码。在这种情况下,我们总是同时屏蔽与一个单词对应的所有标记。总体掩蔽率保持不变。

Whole Word Masked Input: man [MASK] up , put his basket on [MASK] [MASK] [MASK]’s head

训练是相同的——我们仍然独立地预测每个掩码的 WordPiece 标记。改进来自这样一个事实,即原始预测任务对于已拆分为多个 WordPieces 的单词来说太“容易”了。

这可以在数据生成期间通过将标志 –do_whole_word_mask=True 传递给 create_pretraining_data.py 来启用。

带有全字掩码的预训练模型链接如下。数据和训练在其他方面是相同的,并且模型具有与原始模型相同的结构和词汇。我们只包括 BERT-Large 模型。使用这些模型时,请在论文中明确说明您使用的是 BERT-Large 的 Whole Word Masking 变体。

  • BERT-Large, Uncased (Whole Word Masking): 24-layer, 1024-hidden, 16-heads, 340M parameters
  • BERT-Large, Cased (Whole Word Masking): 24-layer, 1024-hidden, 16-heads, 340M parameters

2019 年 2 月 7 日新功能:TfHub 模块

BERT 已上传到 TensorFlow Hub。有关如何使用 TF Hub 模块的示例,请参阅 run_classifier_with_tfhub.py,或在 Colab 上的浏览​​器中运行示例。

2018 年 11 月 23 日新增:非标准化多语言模型 + 泰语 + 蒙古语

我们上传了一个新的多语言模型,它不对输入执行任何规范化(没有小写、重音剥离或 Unicode 规范化),还包括泰语和蒙古语。

建议使用此版本开发多语言模型,尤其是非拉丁字母的语言。

这不需要任何代码更改,可以在这里下载:

BERT-Base, Multilingual Cased:104 种语言,12 层,768 隐藏,12 头,110M 参数
2018 年 11 月 15 日新:SOTA SQuAD 2.0 系统

我们发布了代码更改以重现我们 83% 的 F1 SQuAD 2.0 系统,该系统目前以 3% 的优势在排行榜上排名第一。有关详细信息,请参阅 README 的 SQuAD 2.0 部分。

2018 年 11 月 5 日新:提供第三方 PyTorch 和 Chainer 版本的 BERT

HuggingFace 的 NLP 研究人员提供了一个 PyTorch 版本的 BERT,它与我们预训练的检查点兼容,并且能够重现我们的结果。 Sosuke Kobayashi 还提供了 BERT 的 Chainer 版本(谢谢!)我们没有参与 PyTorch 实现的创建或维护,因此请向该存储库的作者提出任何问题。

2018 年 11 月 3 日新功能:提供多语言和中文模式

我们提供了两种新的 BERT 模型:

BERT-Base, Multilingual(不推荐,使用 Multilingual Cased 代替):102 种语言,12 层,768 隐藏,12 头,110M 参数
BERT-Base,中文:中文简繁体,12层,768隐藏,12头,110M参数
我们对中文使用基于字符的标记化,对所有其他语言使用 WordPiece 标记化。两种模型都应该开箱即用,无需更改任何代码。我们确实在 tokenization.py 中更新了 BasicTokenizer 的实现以支持汉字标记化,所以如果你分叉了它,请更新。但是,我们没有更改标记化 API。

有关更多信息,请参阅多语言自述文件。

结束新信息

简介
BERT,或 Transformers 的双向编码器表示,是一种预训练语言表示的新方法,它在各种自然语言处理 (NLP) 任务中获得最先进的结果。

我们的学术论文详细描述了 BERT,并提供了多项任务的完整结果,可以在这里找到:https://arxiv.org/abs/1810.04805。

举几个数字,以下是 SQuAD v1.1 问答任务的结果:

加上许多其他任务。

此外,这些结果都是在几乎没有特定任务的神经网络架构设计的情况下获得的。

如果您已经知道 BERT 是什么并且只想开始,您可以下载预训练模型并在几分钟内运行最先进的微调。

什么是 BERT?
BERT 是一种预训练语言表示的方法,这意味着我们在大型文本语料库(如维基百科)上训练一个通用的“语言理解”模型,然后将该模型用于我们关心的下游 NLP 任务(如问题回答)。 BERT 优于以前的方法,因为它是第一个用于预训练 NLP 的无监督、深度双向系统。

无监督意味着 BERT 仅使用纯文本语料库进行训练,这很重要,因为大量纯文本数据在网络上以多种语言公开可用。

预训练的表示也可以是无上下文的或上下文的,上下文表示还可以是单向的或双向的。 word2vec 或 GloVe 等上下文无关模型为词汇表中的每个单词生成单个“词嵌入”表示,因此 bank 在银行存款和河岸中具有相同的表示。相反,上下文模型会根据句子中的其他单词生成每个单词的表示。

BERT 建立在最近在预训练上下文表示方面的工作之上——包括半监督序列学习、生成预训练、ELMo 和 ULMFit——但至关重要的是,这些模型都是单向或浅双向的。这意味着每个单词仅使用其左侧(或右侧)的单词进行上下文化。例如,在句子 I made a bank deposit 中,bank 的单向表示仅基于 I made a but not deposit。以前的一些工作确实结合了来自单独的左上下文和右上下文模型的表示,但只是以“浅”的方式。 BERT 使用其左右上下文来表示“银行”——我做了一笔存款——从深度神经网络的最底层开始,因此它是深度双向的。

BERT 为此使用了一种简单的方法:我们屏蔽掉输入中 15% 的单词,通过深度双向 Transformer 编码器运行整个序列,然后仅预测被屏蔽的单词。例如:

Input: the man went to the [MASK1] . he bought a [MASK2] of milk.
Labels: [MASK1] = store; [MASK2] = gallon

为了学习句子之间的关系,我们还训练了一个可以从任何单语语料库生成的简单任务:给定两个句子 A 和 B,B 是 A 之后的实际下一个句子,还是只是语料库中的一个随机句子 ?

Sentence A: the man went to the store .
Sentence B: he bought a gallon of milk .
Label: IsNextSentence

Sentence A: the man went to the store .
Sentence B: penguins are flightless .
Label: NotNextSentence

然后我们在大型语料库(Wikipedia + BookCorpus)上长时间(1M 更新步骤)训练一个大型模型(12 层到 24 层 Transformer),这就是 BERT。

使用 BERT 有两个阶段:预训练和微调。

预训练相当昂贵(在 4 到 16 个 Cloud TPU 上需要 4 天),但对于每种语言都是一次性的(当前模型仅支持英语,但多语言模型将在不久的将来发布)。我们正在从论文中发布一些在 Google 进行预训练的预训练模型。大多数 NLP 研究人员永远不需要从头开始预训练他们自己的模型。

微调成本低。从完全相同的预训练模型开始,论文中的所有结果最多可以在单个 Cloud TPU 上复制 1 小时,或者在 GPU 上复制几个小时。例如,可以在单个 Cloud TPU 上对 SQuAD 进行大约 30 分钟的训练,以达到 91.0% 的 Dev F1 分数,这是最先进的单个系统。

BERT 的另一个重要方面是它可以很容易地适应多种类型的 NLP 任务。在本文中,我们展示了句子级别(例如,SST-2)、句子对级别(例如,MultiNLI)、单词级别(例如,NER)和跨度级别的最新结果(例如,SQuAD)任务,几乎没有针对特定任务的修改。

此存储库中发布了什么?
我们正在发布以下内容:

BERT 模型架构(主要是标准的 Transformer 架构)的 TensorFlow 代码。
论文中 BERT-Base 和 BERT-Large 的小写和大写版本的预训练检查点。
TensorFlow 代码用于一键复制论文中最重要的微调实验,包括 SQuAD、MultiNLI 和 MRPC。
此存储库中的所有代码都可与 CPU、GPU 和 Cloud TPU 一起使用。

预训练模型
我们正在发布论文中的 BERT-Base 和 BERT-Large 模型。 Uncased 表示文本在 WordPiece 标记化之前已小写,例如,John Smith 变为 john smith。 Uncased 模型还去掉了任何重音标记。大小写意味着保留真实的大小写和重音标记。通常,除非您知道案例信息对您的任务很重要(例如,命名实体识别或词性标记),否则 Uncased 模型会更好。

这些模型都是在与源代码 (Apache 2.0) 相同的许可下发布的。

有关多语言和中文模型的信息,请参阅多语言自述文件。

使用案例模型时,请确保将 –do_lower=False 传递给训练脚本。 (或者如果您使用自己的脚本,则直接将 do_lower_case=False 传递给 FullTokenizer。)

模型的链接在这里(右键单击名称上的“将链接另存为…”):

  • BERT-Large, Uncased (Whole Word Masking): 24-layer, 1024-hidden, 16-heads, 340M parameters
  • BERT-Large, Cased (Whole Word Masking): 24-layer, 1024-hidden, 16-heads, 340M parameters
  • BERT-Base, Uncased: 12-layer, 768-hidden, 12-heads, 110M parameters
  • BERT-Large, Uncased: 24-layer, 1024-hidden, 16-heads, 340M parameters
  • BERT-Base, Cased: 12-layer, 768-hidden, 12-heads , 110M parameters
  • BERT-Large, Cased: 24-layer, 1024-hidden, 16-heads, 340M parameters
  • BERT-Base, Multilingual Cased (New, recommended): 104 languages, 12-layer, 768-hidden, 12-heads, 110M parameters
  • BERT-Base, Multilingual Uncased (Orig, not recommended) (Not recommended, use Multilingual Casedinstead): 102 languages, 12-layer, 768-hidden, 12-heads, 110M parameters
  • BERT-Base, Chinese: Chinese Simplified and Traditional, 12-layer, 768-hidden, 12-heads, 110M parameters

每个 .zip 文件包含三个项目:

包含预训练权重(实际上是 3 个文件)的 TensorFlow 检查点 (bert_model.ckpt)。
用于将 WordPiece 映射到单词 id 的词汇文件 (vocab.txt)。
一个配置文件 (bert_config.json),它指定模型的超参数。
使用 BERT 进行微调
重要提示:本文中的所有结果均在具有 64GB RAM 的单个 Cloud TPU 上进行了微调。目前无法使用具有 12GB – 16GB RAM 的 GPU 在纸上重新生成大部分 BERT-Large 结果,因为内存中可以容纳的最大批大小太小。我们正在努力将代码添加到此存储库,以允许在 GPU 上实现更大的有效批量大小。有关更多详细信息,请参阅有关内存不足问题的部分。

此代码已使用 TensorFlow 1.11.0 进行了测试。它使用 Python2 和 Python3 进行了测试(但更彻底地使用了 Python2,因为这是 Google 内部使用的)。

使用 BERT-Base 的微调示例应该能够使用给定的超参数在具有至少 12GB RAM 的 GPU 上运行。

使用 Cloud TPU 进行微调
下面的大多数示例都假设您将使用 Titan X 或 GTX 1080 等 GPU 在本地机器上运行训练/评估。

但是,如果您有权访问要训练的 Cloud TPU,只需将以下标志添加到 run_classifier.py 或 run_squad.py:

  --use_tpu=True \
  --tpu_name=$TPU_NAME


请参阅 Google Cloud TPU 教程,了解如何使用 Cloud TPU。或者,您可以使用 Google Colab 笔记本“BERT FineTuning with Cloud TPUs”。

在 Cloud TPU 上,预训练模型和输出目录需要位于 Google Cloud Storage 上。例如,如果您有一个名为 some_bucket 的存储桶,则可以改用以下标志:

–output_dir=gs://some_bucket/my_output_dir/
解压后的预训练模型文件也可以在 Google Cloud Storage 文件夹 gs://bert_models/2018_10_18 中找到。例如:

导出 BERT_BASE_DIR=gs://bert_models/2018_10_18/uncased_L-12_H-768_A-12
句子(和句子对)分类任务
在运行此示例之前,您必须通过运行此脚本下载 GLUE 数据并将其解压缩到某个目录 $GLUE_DIR。接下来,下载 BERT-Base 检查点并将其解压缩到某个目录 $BERT_BASE_DIR。

此示例代码在 Microsoft Research Paraphrase Corpus (MRPC) 语料库上对 BERT-Base 进行微调,该语料库仅包含 3,600 个示例,并且可以在大多数 GPU 上在几分钟内进行微调。

export BERT_BASE_DIR=/path/to/bert/uncased_L-12_H-768_A-12
export GLUE_DIR=/path/to/glue

python run_classifier.py \
  --task_name=MRPC \
  --do_train=true \
  --do_eval=true \
  --data_dir=$GLUE_DIR/MRPC \
  --vocab_file=$BERT_BASE_DIR/vocab.txt \
  --bert_config_file=$BERT_BASE_DIR/bert_config.json \
  --init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \
  --max_seq_length=128 \
  --train_batch_size=32 \
  --learning_rate=2e-5 \
  --num_train_epochs=3.0 \
  --output_dir=/tmp/mrpc_output/

你应该看到这样的输出:

***** Eval results *****
  eval_accuracy = 0.845588
  eval_loss = 0.505248
  global_step = 343
  loss = 0.505248

这意味着开发集准确率为 84.55%。即使从相同的预训练检查点开始,像 MRPC 这样的小集在 Dev 集的准确性上也有很大的差异。如果您重新运行多次(确保指向不同的 output_dir),您应该会看到 84% 到 88% 之间的结果。

其他一些预训练模型在 run_classifier.py 中现成实现,因此按照这些示例将 BERT 用于任何单句或句子对分类任务应该很简单。

注意:您可能会看到一条消息正在 CPU 上运行火车。这实际上只是意味着它运行在包含 GPU 的 Cloud TPU 以外的其他东西上。

分类器的预测
训练好分类器后,您可以使用 –do_predict=true 命令在推理模式下使用它。您需要在输入文件夹中有一个名为 test.tsv 的文件。输出将在输出文件夹中名为 test_results.tsv 的文件中创建。每行将包含每个样本的输出,列是类概率。

export BERT_BASE_DIR=/path/to/bert/uncased_L-12_H-768_A-12
export GLUE_DIR=/path/to/glue
export TRAINED_CLASSIFIER=/path/to/fine/tuned/classifier

python run_classifier.py \
  --task_name=MRPC \
  --do_predict=true \
  --data_dir=$GLUE_DIR/MRPC \
  --vocab_file=$BERT_BASE_DIR/vocab.txt \
  --bert_config_file=$BERT_BASE_DIR/bert_config.json \
  --init_checkpoint=$TRAINED_CLASSIFIER \
  --max_seq_length=128 \
  --output_dir=/tmp/mrpc_output/

SQuAD 1.1

斯坦福问答数据集 (SQuAD) 是一个流行的问答基准数据集。 BERT(在发布时)在 SQuAD 上获得了最先进的结果,几乎没有针对特定任务的网络架构修改或数据增强。 然而,它确实需要半复杂的数据预处理和后处理来处理(a)SQuAD 上下文段落的可变长度性质,以及(b)用于 SQuAD 训练的字符级答案注释。 此处理在 run_squad.py 中实现和记录。

要在 SQuAD 上运行,您首先需要下载数据集。 SQuAD 网站似乎不再链接到 v1.1 数据集,但可以在此处找到必要的文件:

  • train-v1.1.json
  • dev-v1.1.json
  • evaluate-v1.1.py

将这些下载到某个目录 $SQUAD_DIR。

由于内存限制,论文中最先进的 SQuAD 结果目前无法在 12GB-16GB GPU 上重现(事实上,即使批量大小 1 似乎也不适合使用 BERT-Large 的 12GB GPU)。 但是,可以使用以下超参数在 GPU 上训练一个相当强大的 BERT-Base 模型:

python run_squad.py \
  --vocab_file=$BERT_BASE_DIR/vocab.txt \
  --bert_config_file=$BERT_BASE_DIR/bert_config.json \
  --init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \
  --do_train=True \
  --train_file=$SQUAD_DIR/train-v1.1.json \
  --do_predict=True \
  --predict_file=$SQUAD_DIR/dev-v1.1.json \
  --train_batch_size=12 \
  --learning_rate=3e-5 \
  --num_train_epochs=2.0 \
  --max_seq_length=384 \
  --doc_stride=128 \
  --output_dir=/tmp/squad_base/

开发集预测将保存到 output_dir 中名为 predictions.json 的文件中:

python $SQUAD_DIR/evaluate-v1.1.py $SQUAD_DIR/dev-v1.1.json ./squad/predictions.json
{"f1": 88.41249612335034, "exact_match": 81.2488174077578}

您应该会看到类似于论文中报告的 BERT-Base 的 88.5% 的结果。

如果您可以访问 Cloud TPU,则可以使用 BERT-Large 进行训练。 这是一组超参数(与论文略有不同),它们始终获得大约 90.5%-91.0% 仅在 SQuAD 上训练的 F1 单系统:

python run_squad.py \
  --vocab_file=$BERT_LARGE_DIR/vocab.txt \
  --bert_config_file=$BERT_LARGE_DIR/bert_config.json \
  --init_checkpoint=$BERT_LARGE_DIR/bert_model.ckpt \
  --do_train=True \
  --train_file=$SQUAD_DIR/train-v1.1.json \
  --do_predict=True \
  --predict_file=$SQUAD_DIR/dev-v1.1.json \
  --train_batch_size=24 \
  --learning_rate=3e-5 \
  --num_train_epochs=2.0 \
  --max_seq_length=384 \
  --doc_stride=128 \
  --output_dir=gs://some_bucket/squad_large/ \
  --use_tpu=True \
  --tpu_name=$TPU_NAME

例如,使用这些参数进行一次随机运行会产生以下 Dev 分数:

{"f1": 90.87081895814865, "exact_match": 84.38978240302744}

如果您在此之前在 TriviaQA 上微调一个 epoch,结果会更好,但您需要将 TriviaQA 转换为 SQuAD json 格式。

SQuAD 2.0
该模型也在 run_squad.py 中实现和记录。

要在 SQuAD 2.0 上运行,您首先需要下载数据集。 必要的文件可以在这里找到:

  • train-v2.0.json
  • dev-v2.0.json
  • evaluate-v2.0.py

将这些下载到某个目录 $SQUAD_DIR。

在 Cloud TPU 上,您可以使用 BERT-Large 运行,如下所示:

python run_squad.py \
  --vocab_file=$BERT_LARGE_DIR/vocab.txt \
  --bert_config_file=$BERT_LARGE_DIR/bert_config.json \
  --init_checkpoint=$BERT_LARGE_DIR/bert_model.ckpt \
  --do_train=True \
  --train_file=$SQUAD_DIR/train-v2.0.json \
  --do_predict=True \
  --predict_file=$SQUAD_DIR/dev-v2.0.json \
  --train_batch_size=24 \
  --learning_rate=3e-5 \
  --num_train_epochs=2.0 \
  --max_seq_length=384 \
  --doc_stride=128 \
  --output_dir=gs://some_bucket/squad_large/ \
  --use_tpu=True \
  --tpu_name=$TPU_NAME \
  --version_2_with_negative=True

我们假设您已将从输出目录复制到名为的本地目录。/ squad/。 初始DEV SET预测将在./squad/predictions.json和每个问题的最佳答案(“”)和最佳非空答案之间的差异将在文件中。/ squad/null_odds.json

运行此脚本以调整预测NULL与非空答案的阈值:

python $ squad_dir / evaluate-v2.0.py $ squad_dir / dev-v2.0.json ./squad/predictions.json – prob-file ./squad/null_odds.json

假设脚本输出“best_f1_thresh”阈值。 (典型值在-1.0和-5.0之间)。 您现在可以重新运行模型以使用派生阈值生成预测,或者您可以从。/squad/nbest_predictions.json提取适当的答案。

python run_squad.py \
  --vocab_file=$BERT_LARGE_DIR/vocab.txt \
  --bert_config_file=$BERT_LARGE_DIR/bert_config.json \
  --init_checkpoint=$BERT_LARGE_DIR/bert_model.ckpt \
  --do_train=False \
  --train_file=$SQUAD_DIR/train-v2.0.json \
  --do_predict=True \
  --predict_file=$SQUAD_DIR/dev-v2.0.json \
  --train_batch_size=24 \
  --learning_rate=3e-5 \
  --num_train_epochs=2.0 \
  --max_seq_length=384 \
  --doc_stride=128 \
  --output_dir=gs://some_bucket/squad_large/ \
  --use_tpu=True \
  --tpu_name=$TPU_NAME \
  --version_2_with_negative=True \
  --null_score_diff_threshold=$THRESH

内存溢出的问题
本文中的所有实验都在云TPU上进行微调,具有64GB的设备RAM。因此,使用带12GB – 16GB的RAM的GPU时,如果使用纸纸中描述的相同的超参数,则可能会遇到内存中的问题。

影响内存使用的因素是:

max_seq_length:发布的模型培训,序列长度高达512,但您可以使用较短的最大序列长度进行微调,以节省大量内存。这由我们的示例代码中的max_seq_length标志控制。

TRAIN_BATCH_SIZE:内存使用率也与批处理大小成比例。

模型类型,BERT-BASE与BERT-LIGHT:BERT-MAT​​RIC型号比BERT基本要显着更多的内存。

优化器:BERT的默认优化器是ADAM,这需要大量额外的内存来存储M和V向量。切换到更多内存高效的优化器可以减少内存使用情况,但也可以影响结果。我们没有尝试使用其他优化器进行微调。

使用默认的培训脚本(run_classifier.py和run_squad.py),我们通过Tensorflow 1.11.0基准于 Titan X GPU (12GB RAM)上的最大批量大小:

不幸的是,BERT-Large 的这些最大批量大小非常小,以至于无论使用何种学习率,它们实际上都会损害模型的准确性。我们正在努力向这个存储库添加代码,这将允许在 GPU 上使用更大的有效批量大小。该代码将基于以下一种(或两种)技术:

梯度累积:小批量中的样本通常独立于梯度计算(不包括批量归一化,此处未使用)。这意味着可以在执行权重更新之前累积多个较小 minibatch 的梯度,这将完全等同于单个较大的更新。

梯度检查点:在 DNN 训练期间 GPU/TPU 内存的主要用途是缓存正向传递中的中间激活,这是反向传递中高效计算所必需的。 “梯度检查点”通过以智能方式重新计算激活来用内存换取计算时间。

但是,这在当前版本中没有实现。

使用 BERT 提取固定特征向量(如 ELMo)
在某些情况下,与其对整个预训练模型进行端到端微调,不如获得预训练的上下文嵌入,这是从预训练的隐藏层生成的每个输入标记的固定上下文表示。 – 训练模型。这也应该可以缓解大多数内存不足的问题。

例如,我们包含脚本 extract_features.py 可以像这样使用:

# Sentence A and Sentence B are separated by the ||| delimiter for sentence
# pair tasks like question answering and entailment.
# For single sentence inputs, put one sentence per line and DON'T use the
# delimiter.
echo 'Who was Jim Henson ? ||| Jim Henson was a puppeteer' > /tmp/input.txt

python extract_features.py \
  --input_file=/tmp/input.txt \
  --output_file=/tmp/output.jsonl \
  --vocab_file=$BERT_BASE_DIR/vocab.txt \
  --bert_config_file=$BERT_BASE_DIR/bert_config.json \
  --init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \
  --layers=-1,-2,-3,-4 \
  --max_seq_length=128 \
  --batch_size=8

这将创建一个 JSON 文件(每行输入一行),其中包含来自层指定的每个 Transformer 层的 BERT 激活(-1 是 Transformer 的最终隐藏层等)

请注意,此脚本将生成非常大的输出文件(默认情况下,每个输入标记大约 15kb)。

如果您需要保持原始单词和标记化单词之间的对齐(用于投影训练标签),请参阅下面的标记化部分。

注意:您可能会看到一条消息,例如在 model_dir: /tmp/tmpuB5g5c 中找不到训练好的模型,正在运行初始化以进行预测。此消息是预期的,它只是意味着我们使用的是 init_from_checkpoint() API,而不是保存的模型 API。如果您没有指定检查点或指定无效的检查点,此脚本会报错。

代币化
对于句子级任务(或句子对)任务,标记化非常简单。只需按照 run_classifier.py 和 extract_features.py 中的示例代码进行操作即可。句子级任务的基本过程是:

实例化 tokenizer = tokenization.FullTokenizer 的实例

使用 tokens = tokenizer.tokenize(raw_text) 对原始文本进行标记。

截断到最大序列长度。 (您最多可以使用 512,但出于内存和速度原因,您可能希望使用更短的时间。)

在正确的位置添加 [CLS] 和 [SEP] 令牌。

单词级别和跨度级别的任务(例如,SQuAD 和 NER)更复杂,因为您需要保持输入文本和输出文本之间的对齐,以便您可以投射训练标签。 SQuAD 是一个特别复杂的示例,因为输入标签是基于字符的,并且 SQuAD 段落通常比我们的最大序列长度长。请参阅 run_squad.py 中的代码以显示我们如何处理此问题。

在我们描述处理单词级任务的一般方法之前,了解我们的分词器到底在做什么是很重要的。它有三个主要步骤:

文本规范化:将所有空白字符转换为空格,并且(对于 Uncased 模型)小写输入并去除重音标记。例如,约翰·约翰逊的,→ 约翰·约翰逊的,。

标点拆分:拆分两边的所有标点字符(即在所有标点字符周围添加空格)。标点字符被定义为 (a) 任何具有 P* Unicode 类的字符,(b) 任何非字母/数字/空格的 ASCII 字符(例如,像 $ 这样的字符在技术上不是标点符号)。例如,john johanson’s, → john johanson’s ,

WordPiece 标记化:将空白标记化应用于上述过程的输出,并将 WordPiece 标记化分别应用于每个标记。 (我们的实现直接基于来自 tensor2tensor 的实现,它是链接的)。例如,john johanson’s , → john johan ##son’s ,

这种方案的优点是它与大多数现有的英语分词器“兼容”。例如,假设您有一个词性标注任务,如下所示:

输入: John Johanson 's house
标签: NNP NNP POS NN
标记化的输出将如下所示:

代币:john johan ##son 的房子
至关重要的是,这将与原始文本是 John Johanson 的房子的输出相同(在 ‘s 之前没有空格)。

如果您有一个带有单词级别注释的预标记表示,您可以简单地独立标记每个输入单词,并确定性地保持原始到标记的对齐方式:

### Input
orig_tokens = ["John", "Johanson", "'s",  "house"]
labels      = ["NNP",  "NNP",      "POS", "NN"]

### Output
bert_tokens = []

# Token map will be an int -> int mapping between the `orig_tokens` index and
# the `bert_tokens` index.
orig_to_tok_map = []

tokenizer = tokenization.FullTokenizer(
    vocab_file=vocab_file, do_lower_case=True)

bert_tokens.append("[CLS]")
for orig_token in orig_tokens:
  orig_to_tok_map.append(len(bert_tokens))
  bert_tokens.extend(tokenizer.tokenize(orig_token))
bert_tokens.append("[SEP]")

# bert_tokens == ["[CLS]", "john", "johan", "##son", "'", "s", "house", "[SEP]"]
# orig_to_tok_map == [1, 2, 4, 6]

现在 orig_to_tok_map 可用于将标签投影到标记化表示。

有一些常见的英语标记化方案会导致 BERT 的预训练方式略有不匹配。例如,如果您的输入标记化拆分了类似 do n’t 的缩略词,这将导致不匹配。如果可以这样做,您应该预处理您的数据以将它们转换回看起来很原始的文本,但如果不可能,这种不匹配可能不是什么大问题。

使用 BERT 进行预训练
我们正在发布代码来对任意文本语料库进行“蒙面 LM”和“下一句预测”。请注意,这不是论文中使用的确切代码(原始代码是用 C++ 编写的,并且有一些额外的复杂性),但该代码确实会生成论文中描述的预训练数据。

以下是如何运行数据生成。输入是一个纯文本文件,每行一个句子。 (重要的是这些是“下一句预测”任务的实际句子)。文档由空行分隔。输出是一组序列化为 TFRecord 文件格式的 tf.train.Examples。

您可以使用现成的 NLP 工具包(例如 spaCy)执行句子分割。 create_pretraining_data.py 脚本将连接段,直到它们达到最大序列长度,以最大限度地减少填充造成的计算浪费(有关更多详细信息,请参阅脚本)。但是,您可能希望有意在输入数据中添加少量噪声(例如,随机截断 2% 的输入段),以使其在微调期间对非句子输入更加稳健。

该脚本将整个输入文件的所有示例存储在内存中,因此对于大型数据文件,您应该对输入文件进行分片并多次调用该脚本。 (您可以将文件 glob 传递给 run_pretraining.py,例如 tf_examples.tf_record*。)

max_predictions_per_seq 是每个序列的掩码 LM 预测的最大数量。您应该将其设置为大约 max_seq_length * masked_lm_prob (脚本不会自动执行此操作,因为需要将确切的值传递给两个脚本)。

python create_pretraining_data.py \
  --input_file=./sample_text.txt \
  --output_file=/tmp/tf_examples.tfrecord \
  --vocab_file=$BERT_BASE_DIR/vocab.txt \
  --do_lower_case=True \
  --max_seq_length=128 \
  --max_predictions_per_seq=20 \
  --masked_lm_prob=0.15 \
  --random_seed=12345 \
  --dupe_factor=5

以下是如何进行预训练。 如果您是从头开始预训练,请不要包含 init_checkpoint。 模型配置(包括词汇大小)在 bert_config_file 中指定。 此演示代码仅对少量步骤 (20) 进行预训练,但实际上您可能希望将 num_train_steps 设置为 10000 步或更多。 传递给 run_pretraining.py 的 max_seq_length 和 max_predictions_per_seq 参数必须与 create_pretraining_data.py 相同。

python run_pretraining.py \
  --input_file=/tmp/tf_examples.tfrecord \
  --output_dir=/tmp/pretraining_output \
  --do_train=True \
  --do_eval=True \
  --bert_config_file=$BERT_BASE_DIR/bert_config.json \
  --init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \
  --train_batch_size=32 \
  --max_seq_length=128 \
  --max_predictions_per_seq=20 \
  --num_train_steps=20 \
  --num_warmup_steps=10 \
  --learning_rate=2e-5

这将产生如下输出:

***** Eval results *****
  global_step = 20
  loss = 0.0979674
  masked_lm_accuracy = 0.985479
  masked_lm_loss = 0.0979328
  next_sentence_accuracy = 1.0
  next_sentence_loss = 3.45724e-05

请注意,由于我们的 sample_text.txt 文件非常小,因此此示例训练将在几个步骤中过度拟合该数据并产生不切实际的高精度数字。

预训练提示和注意事项
如果使用您自己的词汇表,请确保更改 bert_config.json 中的 vocab_size。如果你使用更大的词汇量而不改变这一点,那么在 GPU 或 TPU 上训练时,由于未经检查的越界访问,你可能会得到 NaN。
如果您的任务有大量特定领域的语料库可用(例如,“电影评论”或“科学论文”),那么从 BERT 检查点开始对您的语料库进行额外的预训练步骤可能会有所帮助。
我们在论文中使用的学习率为 1e-4。但是,如果您从现有的 BERT 检查点开始执行额外的预训练步骤,则应使用较小的学习率(例如 2e-5)。
当前的 BERT 模型仅支持英语,但我们确实计划在不久的将来(希望在 2018 年 11 月末)发布一个已在多种语言上进行预训练的多语言模型。
较长的序列成本不成比例,因为注意力与序列长度成二次方。换句话说,一批 64 个长度为 512 的序列比一批 256 个长度为 128 的序列要昂贵得多。全连接/卷积成本相同,但 512 长度序列的注意力成本要高得多.因此,一个好的方法是预先训练 90,000 步,序列长度为 128,然后再进行 10,000 步,序列长度为 512。学习位置嵌入通常需要非常长的序列,这可以学得还算快。请注意,这确实需要使用不同的 max_seq_length 值生成两次数据。
如果您是从头开始进行预训练,请准备好预训练的计算成本很高,尤其是在 GPU 上。如果您是从头开始进行预训练,我们推荐的方法是在单个可抢占 Cloud TPU v2 上预训练 BERT-Base,这需要大约 2 周时间,成本约为 500 美元(基于 2018 年 10 月的定价) .与论文中使用的相比,仅在单个 Cloud TPU 上进行训练时,您将不得不缩小批量大小。建议使用适合 TPU 内存的最大批量大小。
预训练数据
我们将无法发布论文中使用的预处理数据集。对于 Wikipedia,推荐的预处理是下载最新的转储,使用 WikiExtractor.py 提取文本,然后应用任何必要的清理将其转换为纯文本。

不幸的是,收集 BookCorpus 的研究人员不再提供公开下载。 Project Guttenberg 数据集是一个较小的(2 亿字)公共领域的旧书集合。

Common Crawl 是另一个非常大的文本集合,但您可能需要进行大量的预处理和清理以提取可用的语料库以用于预训练 BERT。

学习一个新的 WordPiece 词汇
此存储库不包含用于学习新 WordPiece 词汇的代码。原因是论文中使用的代码是用 C++ 实现的,依赖于 Google 的内部库。对于英语,从我们的词汇和预训练模型开始几乎总是更好。对于学习其他语言的词汇,有许多可用的开源选项。但是,请记住,这些与我们的 tokenization.py 库不兼容:

  • Google’s SentencePiece library
  • tensor2tensor’s WordPiece generation script
  • Rico Sennrich’s Byte Pair Encoding library

在 Colab 中使用 BERT
如果您想将 BERT 与 Colab 一起使用,您可以从笔记本“BERT FineTuning with Cloud TPUs”开始。在撰写本文时(2018 年 10 月 31 日),Colab 用户可以完全免费访问 Cloud TPU。注意:每位用户一个,可用性有限,需要一个带有存储空间的 Google Cloud Platform 帐户(尽管注册 GCP 时可以使用免费信用购买存储空间),并且此功能将来可能不再可用。单击刚刚链接的 BERT Colab 以获取更多信息。

常问问题
此代码与 Cloud TPU 兼容吗? GPU 呢?
是的,这个存储库中的所有代码都可以与 CPU、GPU 和 Cloud TPU 一起使用。但是,GPU 训练仅限于单 GPU。

我收到内存不足错误,怎么了?
有关更多信息,请参阅有关内存不足问题的部分。

有可用的 PyTorch 版本吗?
没有官方的 PyTorch 实现。然而,来自 HuggingFace 的 NLP 研究人员提供了一个 PyTorch 版本的 BERT,它与我们预训练的检查点兼容,并且能够重现我们的结果。我们没有参与 PyTorch 实现的创建或维护,因此请向该存储库的作者提出任何问题。

是否有可用的 Chainer 版本?
没有官方的 Chainer 实现。然而,Sosuke Kobayashi 提供了 BERT 的 Chainer 版本,它与我们预先训练的检查点兼容,并且能够重现我们的结果。我们没有参与 Chainer 实现的创建或维护,因此请向该存储库的作者提出任何问题。

是否会发布其他语言的模型?
是的,我们计划在不久的将来发布多语言 BERT 模型。我们无法就将包含哪些语言做出确切承诺,但它可能是一个单一模型,其中包含大多数拥有庞大维基百科的语言。

是否会发布比 BERT-Large 更大的模型?
到目前为止,我们还没有尝试训练任何比 BERT-Large 更大的东西。如果我们能够获得重大改进,我们可能会发布更大的模型。

这个库是在什么许可证下发布的?
所有代码和模型均在 Apache 2.0 许可下发布。有关详细信息,请参阅许可证文件。

我如何引用 BERT?
现在,引用 the Arxiv paper:

@article{devlin2018bert,
  title={BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding},
  author={Devlin, Jacob and Chang, Ming-Wei and Lee, Kenton and Toutanova, Kristina},
  journal={arXiv preprint arXiv:1810.04805},
  year={2018}
}

如果我们将论文提交给会议或期刊,我们将更新 BibTeX。

免责声明
这不是 Google 的官方产品。

联系信息
有关使用 BERT 的帮助或问题,请提交 GitHub 问题。

有关 BERT 的个人交流,请联系 Jacob Devlin (jacobdevlin@google.com)、Ming-Wei Chang (mingweichang@google.com) 或 Kenton Lee (kentonl@google.com)。

作者 east
人工智能 3月 14,2021

人工智能最全学习教程(持续更新)





学习视频:

零基础学Python

Python教程-零基础快速入门知识

手把手教你学Python(进阶篇)

Python入门到精通

Python高薪实战训练营

Python零基础数据分析与机器学习

Python编程零基础入门到精通体系课 数据分析机器学习Web开发应用

利用Python做验证码的识别

Python爬虫scrapy框架速通教程

机器学习入门到实战( 手推算法)

大数据时代的知识图谱(一线大厂经验)

唐宇迪2天自然语言处理训练营/NLP架构实战/神经网络/深度学习

逆战2020、学人工智能用代码观疫情

作者 east
python, 人工智能 2月 21,2021

精心挑选的100多种机器学习数据集

毫无疑问,每个人都知道,学习数据科学和机器学习的唯一最佳方法是通过执行各种项目来学习它们。老实说,您周围有很多现实世界的机器学习数据集,即使您不必完成全面的数据科学或机器学习课程,也可以选择练习基础数据科学和机器学习技能。但是是的,数据科学和机器学习项目绝对没有其他选择。大多数数据科学和机器学习初学者做错的事情是,他们只是专注于学习许多理论概念,而等待太长时间才能启动专注于该概念的实际实现的机器学习/数据科学项目。毫无疑问,从理论上讲清楚您的机器学习概念总会很好,但是如果没有获得相关的实际经验,您就无法期望成为企业数据科学家或机器学习工程师。在此博客的此处,我们将为您提供100多个有价值的数据集,以供机器学习(特别是对于初学者)使用,这无疑将有助于验证您的基本数据科学和机器学习技能。

机器学习中的数据集是什么?
机器学习中的数据集是实例的集合(实例是指一行数据),这些实例都共享一些共同的特征和属性。为了使机器学习模型执行不同的动作,需要两种数据集–

训练数据集-送入机器学习算法进行训练的数据。

测试数据集或验证数据集–用于评估和测试机器学习模型正在正确解释的数据。

为什么需要机器学习数据集?
机器学习算法从数据中学习。机器学习算法可识别趋势,关系并根据为训练模型而提供的大量数据进行预测。因此,数据是机器学习中的金鹅。从机器学习模型中收集的见解与数据集一样好。对于机器学习项目而言,拥有大量且更好的训练数据可带来更好而准确的模型性能。可靠的机器学习数据集非常重要,并且在精确的机器学习模型的开发中起着至关重要的作用。

可在此处免费访问已解决的机器学习Python和R代码示例(这些已为您的项目准备使用)

在哪里可以找到用于机器学习的数据集?
有大量的免费和付费资源可用于机器学习数据集。公共机器学习数据集可帮助您入门的最受欢迎资源包括–

UCI或UC Irvine机器学习数据集存储库
AWS数据集
Google数据集搜索
数据政府
微软研究开放数据
卡格勒
世界银行
但是,对于数据科学和机器学习的初学者来说,从这些网站上提供的众多选项中进行选择可能会变得势不可挡。如果您想学习机器学习,则需要一个坚实的基础,这意味着用于机器学习项目的有趣数据集,以及一些可以使用这些免费数据集的很棒的项目构想。想知道在哪里可以找到免费和公共的机器学习数据集?别无所求……无论是零售,医疗保健,银行与金融,犯罪,还是其他任何类型的机器学习数据集,我们都精选了一系列顶级机器学习数据集,以帮助您使模型成功。

面向数据科学和机器学习从业人员的100多种机器学习数据集
机器学习数据集

我们汇总了一个以领域为中心的顶级机器学习数据集列表,其中包含对数据和可以使用特定数据集进行的项目的简短描述。

零售机器学习数据集
医疗保健机器学习数据集
银行和金融机器学习数据集
社交媒体机器学习数据集
犯罪机器学习数据集

机器学习的最佳零售数据集
机器学习的零售数据集
零售交易机器学习数据集
1)在线零售数据集(英国在线商店)

如果您热衷于预处理大型零售数据集,则可能希望查找这家英国的在线公司的交易数据,该数据可以出售独特的全场合赠品。 分类和聚类具有超过500,000行和8个属性,是可以使用此数据集执行的最常见的关联机器学习任务。

 Download Online Retail Dataset for Machine Learning

 Interesting Machine Learning Project Idea using UK Online Retail Dataset– Perform Market Basket Analysis to identify the association rules between the products.

2)零售火箭推荐系统数据集

该数据集由真实世界电子商务网站的点击流数据组成,该网站具有有关客户行为的信息,例如添加到购物车信息,交易和点击以及有关417053个唯一商品的不同商品属性的信息。 数据集具有事件数据文件,其中包含有关用户在特定时间戳下对产品执行的事件(添加到购物车,交易或视图)的信息。 仅当用户进行交易时,事件数据文件中的“ transaction-id”列才具有值,否则为N / A。

Download Retail Rocket Recommender System Dataset for Machine Learning

Machine Learning Project Idea using Retail Rocket Machine Learning Dataset – Build a Recommender System to predict the transaction and event pattern of a visitor.

3)用于机器学习的Instacart订单数据集

这是另一个有趣的机器学习数据集,可处理200,000多个Instacart匿名客户的杂货订单,该数据集可用于处理大型零售数据。对于每个客户,数据集均包含购买产品的顺序中4到100个订单的数据以及一天中的星期几和小时数。 XGBoost,Word2Vec和Annoy是机器学习算法,彻底改变了Instacart客户如今购买杂货的方式。


Download Instacart Orders Kaggle Dataset

使用Instacart数据集的初学者的机器学习/数据科学项目创意

客户细分–建立基于关联的机器学习模型,以了解Instacart客户的多样化组合,并针对合适的客户群体以最大程度地提高盈利能力。
市场篮子分析–开发预测性市场篮子分析机器学习模型,以确定Instacart客户将再次购买哪些产品?
4)Olist的巴西电子商务数据集

该机器学习数据集由Olist商店的10万个客户订单数据组成,其中包括卖方信息,产品元数据,客户信息和客户评论的详细信息。



Download Brazilian E-commerce Public Kaggle Dataset by Olist

使用巴西电子商务数据集的数据科学/机器学习项目构想

电子商务产品评论分析–通过分析客户给出的产品评论中的文字对Olist商店出售的产品进行评分。
分析Olist客户的购买趋势,以根据客户当前购买的商品确定客户是否打算购买相关产品。
5)机器学习的超级市场数据集

该零售数据集具有超过1000行和17列,具有一家超市公司3个月的历史销售数据,并记录了该公司三个不同分支机构的数据。该零售数据集是任何类型的预测分析项目的理想选择。


Download Supermarket Kaggle Dataset for Machine Learning

机器学习的零售图像数据集

6)MVTec密集细分的超市图像数据集

由于培训数据数量有限,并且验证和测试集中的多样性很高,因此对于机器学习而言,这是一个具有挑战性的图像数据集。它具有在700个不同场景中采集的日常产品和杂货的21K高分辨率图像,并在与行业相关的设置中以高质量注释为所有对象实例提供了像素化标签。


Download MVTec D2S Retail Dataset for Machine Learning

使用MVTec D2S数据集的计算机视觉项目构想

该零售数据集可用于语义图像分割,以覆盖自动结帐,仓库或库存系统的实际应用。经典的深度学习CNN机器学习算法最适合在像素级别对图像中的产品进行分类,以简化结帐流程。

7)上下文中的通用对象(COCO)数据集

COCO数据集共有330,000张图像,超过200,000个标签,其中包含91个东西类别,80个对象类别,150万个对象实例以及25万具有关键点的人员-COCO数据集是最流行且最具挑战性的高质量计算机视觉数据集之一。该数据集代表了我们在日常生活中遇到的各种物体的图像,被认为是转移学习的理想检查点。它是训练计算机视觉模型的基础数据集。使用COCO计算机视觉数据集训练了任何计算机视觉模型后,您就可以使用任何自定义数据集进一步调整模型以学习其他任务。


Download COCO Dataset for Machine Learning

您可以使用COCO数据集进行哪种计算机视觉项目?

对象检测-使用COCO数据集执行最具挑战性的计算机视觉任务之一,即预测图像中不同对象的位置以及存在的对象的类型。

8)弗莱堡杂货数据集

弗赖堡食品杂货零售数据集包含5000张图像,其中包含25种不同的食品杂货,每个类别至少具有97张图像,这些图像已在不同杂货店的各个部门的实际环境中捕获。


Download Freiburg Groceries Dataset

使用弗莱堡食品杂货集的计算机视觉项目构想

您可以基于杂货产品的多类对象分类构建计算机视觉模型。可以进一步微调此模型,以建立无摩擦的商店体验,类似于流行的Amazon Go商店,而无需手动结帐。

9)时尚MNIST数据集

凭借10K测试示例,60K,培训示例以及10类零售产品,分辨率为28×28灰度通道图像,这是用于深度学习和计算机视觉的MNIST数据集的最佳替代产品之一。但是,这比直接替换更具挑战性。


Download Fashion MNIST Kaggle Dataset

使用Fashion MNIST数据集的计算机视觉项目构想

通过使用Keras或TensorFlow训练简单的CNN从头开始构建模型,使用此数据集来享受您对服装分类的初体验。如果您想练习一种使用CNN机器学习算法解决图像分类问题的方法,则可以查找此数据集。

10)零售产品结帐数据集

在商店货架上有来自2000种不同产品类别的超过500,000张零售商品图像-就产品类别和产品图像数量而言,这是最大的零售图像数据集之一。


Download a Large-Scale Retail Product Checkout Kaggle Dataset

使用RPC数据集的计算机视觉项目构想

该数据集被广泛用于推进零售产品图像识别的研究,以进行自动货架审核和结帐。该数据集的高质量性质使其非常适合用于细粒度的零售产品图像分类。

是否想发展您的数据科学和机器学习技能?查看我们最新的端到端数据科学和机器学习项目以及源代码

客户评论用于机器学习的零售数据集
11)亚马逊客户评论数据集

从1995年到2015年,该机器学习数据集在数百万种产品上拥有超过130亿条客户评论,是机器学习,自然语言处理和信息检索领域的数据科学家和研究人员的福音,以了解客户体验。


Download Amazon Customer Reviews Dataset

12)妇女的电子商务服装评论数据集

这是一个匿名的数据集,因为它包含真实客户撰写的评论,并具有23486个带有10个不同功能变量的客户评论。该ML数据集提供了一个绝佳的环境,可用于解析多个维度的文本。


Download Women’s E-Commerce Clothing Reviews Dataset

13)宜家机器学习评论数据集

这是一个相当小的机器学习数据集,其中包含从Google Maps刮取的1300条最佳和最差的IKEA客户评论。这为情感分析提供了一个完美的初学者级数据集。


Download IKEA Reviews Kaggle Dataset

14)亚马逊和百思买电子产品评论数据集

该数据集专门针对百思买和亚马逊上提供的50种电子产品提供了7000多个在线评论。数据集包括审阅日期,标题,等级,来源,元数据和其他信息。


Download Amazon and Best Buy Electronic Product Reviews Dataset

15)多域情感数据集

这是一个多域数据集,包含来自许多产品类型的产品评论。超过10万条Amazon.com对产品,乐器,书籍和DVD的评论,评分介于1到5之间。


Download Multi-Domain Sentiment Kaggle Dataset

使用客户评论数据集的有趣的机器学习项目创意

使用NLP根据客户评论的内容预测收视率
研究客户反馈对产品购买过程的影响。您可以使用这些评论数据集来预测客户向其朋友推荐产品的可能性。
研究各种品牌的在线声誉。
对客户评论进行情绪分析,以识别用户对产品的情感(正面,负面或中立)。 (评论情绪)
ProjectPro通过构建端到端的现实世界数据科学和机器学习项目来帮助学生学习实践技能。为有源代码的学生检查一些有趣的有趣的机器学习项目构想。

其他用于机器学习的零售数据集
16)来自维多利亚的秘密和其他组织的内衣数据

该数据集包含来自受欢迎的零售网站(如亚马逊,维多利亚的秘密,汉基·潘基,梅西百货,Btemptd,Nordstrom,American Eagle等)的600,000多种内衣产品的数据。


Download Innerwear Data from Victoria’s Secret and Others Kaggle Dataset

使用Innerwear Kaggle数据集的机器学习项目构想:

该数据集可用于分析泳装和内装产品的流行趋势。

17)电子商务项目数据

机器学习数据集包含500个SKU,以及服装品牌产品目录中的产品说明。


Download eCommerce Item Kaggle Dataset

使用电子商务项目Kaggle数据集的机器学习项目构想:

您可以使用Item数据进行的有趣的机器学习项目是构建产品推荐系统。

18)eBay在线拍卖数据集

该在线拍卖零售数据集包含拍卖信息,例如竞标价格,竞标时间,物品的拍卖价格,以及有关施华洛世奇珠子,卡地亚手表,Xbox游戏机和Palm Pilot M515 PDA的其他拍卖信息。


Download eBay Online Auctions Dataset

使用在线拍卖Kaggle数据集的机器学习项目构想:

建立机器学习模型以预测拍卖品的最终价格。从利润最大化的角度来看,预测拍卖品的最终价格对买卖双方都有利。

19)沃尔玛数据集

这是最佳的初学者级机器学习数据集之一,因为它具有最多的零售数据以及每个沃尔玛商店区域中的外部数据,例如失业率,燃料价格,CPI,是进行详细分析的理想选择。该Kaggle数据集包含2010年至2012年记录的45家沃尔玛商店的匿名历史销售数据。


Download Walmart Store Sales Kaggle Dataset

使用沃尔玛零售数据集的机器学习/数据科学项目构想

考虑假日和降价事件,消费者物价指数,季节变化以及其他影响产品销售的因素,建立一个机器学习模型来预测沃尔玛在全部门的销售。销售预测模型可帮助公司草拟有关如何满足未来需求和增加销售的计划。

20)男鞋价格数据集

该数据集包含10,000种男鞋的大集合,以及它们的销售价格,品牌名称,鞋名和其他信息。


Download Men’s Shoe Price Dataset

使用鞋价数据集的机器学习/数据科学项目构想

使用此定价数据建立机器学习模型以-

确定奢侈品牌的品牌价值
确定定价策略
确定奢侈男鞋的趋势
确定鞋子的特定功能与价格变化之间的相关性。

机器学习的最佳医疗保健数据集


用于机器学习的医疗保健数据集

1)OSIC肺纤维化进展

开源影像协会医疗保健数据集包括200例匿名的肺部基线CT扫描以及其他相关临床信息,例如基线强迫生命系数,患者性别,年龄,基线扫描后的相对周数,吸烟状况等。


Download OSIC Pulmonary Fibrosis Progression Dataset

使用OSIC Kaggle数据集的数据科学/机器学习项目构想

您可以建立机器学习模型来预测患者肺功能下降的严重程度。

2)APTOS 2019失明检测

这是在各种成像条件下捕获的眼底摄影视网膜图像的多样化且广泛的数据集。根据糖尿病性视网膜病变的严重程度,每张图片的临床评分为0到4。


Download APTOS 2019 Blindness Detection Kaggle Dataset

使用APTOS数据集的机器学习项目构想

在285万人中,有1/3患有糖尿病性视网膜病变。您可以使用此数据集建立一个机器学习模型,该模型可以在DR引起影响眼睛的并发症之前早发现DR,这将帮助数百万糖尿病患者失去视力。

3)超声神经分割数据集

这个Kaggle数据集包含5635张图像,其中的神经已由人工手动注释。它是具有挑战性的机器学习数据集之一,因为它具有减小的数据大小并且没有明显的结构特征。


Download Ultrasound Nerve Segmentation Dataset

访问带有源代码的该机器学习项目,以建立一个机器学习模型,该模型可识别超声图像中的神经结构,以分割称为臂丛(BP)的神经集合。

4)帕金森数据集

这是一个非常小的医疗数据集,大约需要39 KB的数据,并且可以对31位患者进行一系列生物医学语音测量,其中23位患有帕金森氏病。


Download Parkinson Dataset from UCI Machine Learning Repository

使用帕金森数据集的机器学习项目构想

每年印度有超过100万人受到帕金森氏病的影响。这种疾病是慢性的,无法治愈,甚至很难为医生早期诊断。您可以建立一个机器学习模型,以准确检测个体中帕金森氏病的早期发作,并基于多种因素来确定帕金森氏病患者是否健康。

5)英特尔和MobileODT宫颈癌数据集

该Kaggle数据集包含1481个训练图像和512个测试图像。考虑到此数据集的局限性,您可能必须应用各种数据增强技术来增加训练样本的数量。


Download Intel & MobileODT Cervical Cancer Dataset

使用英特尔和移动ODT宫颈癌数据集的深度学习项目构想

使用深度学习和图像分类的子宫颈类型分类-宫颈癌是致命的,但是如果在早期发现并进行适当治疗,对许多妇女来说可以挽救生命。您可以使用此Kaggle数据集构建深度学习模型,以对子宫颈类型(类型1,类型2和类型3)进行分类,以帮助医疗保健专业人员为全球女性提供更好的护理。对子宫颈类型进行分类将有助于医疗保健提供者提高女性子宫颈癌筛查的效率和质量。

6)乳房组织病理学图像数据集

实际数据集包含162个乳腺癌标本的幻灯片图像。从该数据集中提取了277,524个补丁,其中78786个属于阳性类别,而其余198、738个补丁属于阴性类别。


Download Breast Histopathology Images Dataset

使用乳房组织病理学图像数据集的深度学习项目构想

乳腺癌是最常见的癌症类型,在2018年经诊断的210万例乳腺癌病例中有627,000例死亡报告。在所有确诊的乳腺癌病例中,有80%属于浸润性导管癌(IDC)类型。早期准确诊断癌症有助于选择正确的治疗方案,并有助于提高癌症患者的生存率。您可以使用此数据集构建用于图像分类的深层CNN,以识别未标记的组织病理学图像中IDC的存在。这是一项重要的临床任务,为此,自动化模型肯定会节省时间并减少错误。

7)迷你DDSM数据集

最大的(45GB)公共乳腺摄影数据集之一,具有年龄属性,密度属性,患者的原始文件名,癌病灶轮廓二进制蒙版图像以及带有所有所需元数据的excel表。


Download Mini DDSM Kaggle Dataset

使用Mini DDSM数据集的机器学习项目

年龄估计具有多种临床应用,并且已经使用生物医学图像对人类年龄进行了一些研究。使用此数据集,您可以基于乳房X线照片图像中的胸肌段建立基于AI的模型来估计年龄。最重要的步骤是从乳房X线照片中分割胸肌,然后提取深度学习特征以建立年龄估计模型。

8)克利夫兰心脏病数据集

克利夫兰心脏病UCI数据集包含303个个体的数据,这些个体具有75个属性,其中14个属性,例如年龄,性别,静息血压,血清胆固醇,静息心电图,获得的最大心率,运动诱发的心绞痛以及其他可能的重要参数发生心血管疾病的主要危险因素。


Download Heart Disease Dataset

使用心脏病数据集的机器学习项目构想

心脏病是世界范围内死亡率和发病率的主要原因,仅在美国,每年就有61万例死亡。根据风险因素很难手动确定罹患心血管疾病的几率。在这里,机器学习可以极大地帮助您根据医疗保健行业产生的大量数据做出预测。您可以应用各种机器学习算法,例如SVM,朴素贝叶斯,XGBoost,决策树,随机森林,并使用克利夫兰心脏病机器学习数据集对它们进行比较,以预测某人是否患有心脏病。

9)行动预测数据集的机制

这是一个独特的机器学习数据集,由细胞活力数据和基因表达组成,可以访问超过5K药物的MoA注释。这个用于机器学习的数据集基于一种新颖的技术,该技术可测量人类细胞对数百种不同细胞类型池中药物的反应,从而消除了确定哪种细胞类型更适合任何给定药物的问题。


Download Mechanisms of Action (MoA) Prediction Kaggle Dataset

使用MoA预测数据集的机器学习项目构想

药物发现在疾病治疗的发展中起着至关重要的作用。机器学习被广泛用于理解疾病的潜在机制,临床标记,药物发现和验证。通过开发机器学习算法来基于药物的生物活性对药物进行分类,该数据集可用于促进药物开发。

10)世界卫生组织-医疗机器学习数据集的世界

不同国家/地区最值得信赖和最真实的医疗数据来源。通过针对霍乱,肺结核,流行性感冒和其他疾病等特定疾病的COVID -19数据和分析,世卫组织获得了全球卫生重点数据以及大多数卫生状况的趋势重点。


Download Healthcare Datasets for Machine Learning from WHO Repository

与医疗数据配合使用的其他有趣且有趣的机器学习项目创意

肺分割
糖尿病预测
接触追踪以阻止传染病的传播
癌症分类
个性化医学
预测慢性病
预测疾病暴发
分类图像数据(X射线,CT扫描等)以进行诊断护理。

最佳银行和金融机器学习数据集


机器学习的银行和金融数据集

1)桑坦德数据集

由于这是银行业务数据集,因此已被完全掩盖,仅包含数值。西班牙在线银行桑坦德银行提供了四个不同的数据集,以帮助他们使用机器学习解决各种业务挑战。

ownload Santander Customer Transaction Dataset

Download Santander Value Prediction Dataset

Download Santander Product Recommendation Dataset

Download Santander Customer Satisfaction

这些桑坦德银行数据集可用于构建端到端机器学习模型,以-

预测客户将来是否会与银行进行交易,而不管交易的金额如何。
预测客户是否会购买产品
预测客户是否有能力支付费用
预测客户是否对银行的服务感到满意。
2)房屋信贷违约风险数据集

该数据集包含7个不同的客户数据源-贷款申请数据,局数据,信用卡余额数据,以前的贷款申请数据,POS现金余额数据,EMI付款数据和局余额数据。


Download Home Credit Default Risk Kaggle Dataset

使用房屋信用违约风险Kaggle数据集的机器学习项目构想

建立机器学习模型以预测客户是否有能力偿还贷款。这些模型将帮助银行决定是否只对有能力偿还贷款的申请人批准贷款。

3)银行营业额数据集

该数据集包含针对银行的大约1万名客户的14个功能,其中20%是流失客户。


Download Bank Turnover Dataset

使用银行营业额数据集的机器学习项目

该数据集可用于预测客户流失,这是机器学习的最常见应用之一。您可以建立一个机器学习模型来预测客户是否会在未来6个月内退出银行的服务。预测客户流失将有助于银行制定保留活动和忠诚度计划以保留客户。

4)信用卡交易数据集

该欧洲信用卡数据集包含2013年9月在两天内发生的284、807笔交易和492笔欺诈交易(占所有交易的0.172%)。这是一个极具挑战性的数据集,因为它的数据不平衡,因为大多数这些交易不是欺诈性交易,因此很难检测到欺诈性交易。


Download Credit Card Fraud Transaction Kaggle Dataset

使用信用卡交易数据集的机器学习项目

信用卡欺诈是许多银行和信用卡公司的常见问题,因为大多数欺诈交易看起来与正常交易相似,并且每天在信用卡上完成大量交易,因此很难手动检测到欺诈行为。使用此金融机器学习数据集来识别欺诈性信用卡交易,以确保不会因客户未进行的交易向客户收费。

5)给我一些信用数据集

该数据集包含2008年为25万巴西借款人创建的历史数据,金融机构可以利用这些历史数据来预测信用评分并做出最佳的财务决策。


Download Give me Some Credit Kaggle Dataset

使用“给我一些信誉”数据集的机器学习项目构想

建立一个机器学习模型,以预测一个人在未来两年内遭受财务困扰的可能性。

6)两个西格玛数据集

该数据集由两个数据源组成,即Intrinio和Thomson Reuters。 Intrinio提供的培训市场数据大约有400万行,而路透社提供的培训新闻分析数据则有近900万行,使其成为可用于预测股价的最大数据集之一。


Download Two Sigma Dataset

使用两个Sigma Kaggle数据集的有趣的机器学习项目创意

股票价格通常由投资者的行为决定,而投资者则根据公共信息确定股票价格以预测股票市场的反应。在此,随着投资者对这些信息做出反应,财经新闻文章在影响股票价格方面起着至关重要的作用。该数据集可用于构建机器学习模型,以对与公司列表相关的新闻文章进行分类,并基于该模型预测那些公司的股价波动。

7)比特币历史数据集

该数据集包括从2012年1月到2020年12月的精选比特币交易数据,包括开盘价,最高价,最低价和收盘价的逐分钟更新,以及加权比特币价格,BTC量和指定货币。


Download Bitcoin Historical Dataset

使用比特币历史数据集的示例机器学习项目构想

使用此Kaggle数据集构建机器学习模型,以预测明天的比特币价格。人们可以探索使用LSTM模型来预测比特币价格。

8)简街市场数据集

如果您喜欢机器学习项目或想探索一些良好的股市数据,则此数据集可能是一个绝佳的合作机会。它包含带有匿名功能的真实股市数据,其中数据集中的每一行代表一个交易机会。


Download Jane Street Market Prediction Dataset

使用Jane Street市场预测数据集的建议的机器学习项目

使用Jane Street股票市场数据来构建定量交易机器学习模型,以使用来自全球证券交易所的真实股票市场数据来最大化回报。您还可以针对未来的实际股市数据测试机器学习模型的有效性。

9)Elo商家类别推荐

Elo是巴西的大型支付品牌,向借记卡和信用卡用户提供餐厅推荐,并根据他们的偏好提供折扣。该数据集包含有关每笔卡交易的信息,以及有关特定商人长达3个月的每张卡交易价值的数据,每张卡的新商人的交易详细信息,以及基于交易中涉及的各种商人的其他商人数据。卡交易。


Download Elo Merchant Category Recommendation Dataset

建议的Elo商家类别数据集机器学习项目

该数据集可用于查找这些促销对客户和商人有多有益。建立机器学习模型来预测客户的忠诚度分数,并帮助Elo了解客户的忠诚度,以便他们减少不必要的营销活动并为其用户创造正确的体验。

10)俄罗斯储蓄银行俄罗斯住房市场数据集

此数据集的训练数据包含有关俄罗斯最古老,最大的银行Sberbank的21000个真实交易的信息,而测试数据包含7K个真实交易以及有关该物业的其他信息。


Download Sberbank Russian Housing Market Kaggle Dataset

使用Sberbank俄罗斯住房市场数据集的机器学习项目构想

使用此丰富的银行数据集来开发机器学习模型,以预测实际房价,以便开发商,贷方和提供者在购买物业或签订租约时充满信心。这些数据还包括有关俄罗斯经济和金融部门的信息,这些信息可以帮助开发准确的模型而无需再次猜测。

探索其他100个主要的金融和经济数据集。

机器学习社交媒体数据集
用于机器学习的社交媒体公共数据集

1)Twitter美国航空情绪数据集

该社交媒体数据集具有14,640行和12个属性,并包含从Twitter刮取的美国各主要航空公司的推文。


Download Twitter US Airline Sentiment Dataset

ML项目建议的想法:使用机器学习的情感分类系统

您可以使用此数据集将航空公司的推文分类为肯定,否定或中性,以分析旅行者对航空公司的反馈。

2)Google Cloud和YouTube 8M数据集

由Google AI / Research在2016年开发的数据集,其中包含800万个YouTube视频(总计50万小时)和4.8K(每个视频平均3.4个标签)视觉标题。


Download YouTube 8M Dataset

使用YouTube 8M数据集的数据科学和机器学习项目构想

建立模型大小小于1GB的紧凑型视频分类,以学习视频表示形式。这将有助于推进视频级注释。
建立分类机器学习模型以准确分配视频标签。
3)COVID-19 Tweets数据集

这是一个多语言的推文数据集,包含超过10亿条推文,其中包含冠状病毒,病毒,covid,ncov19,ncov2019等关键字,并带有标签,提及,主题和其他信息。


Download COVID19 Tweets Dataset

使用COVID 19数据集的建议ML项目

使用数据挖掘,网络分析和NLP分析来自该数据集的推文集,以识别人们对大流行的反应以及反应随时间的变化。您还可以利用此ML数据集来收集有关大流行初期如何传输正确信息和错误信息的见解。

4)Yelp数据集

该数据集包含5,200,000条评论,其中包含来自4个国家/地区11个地区的1,74,000家企业的信息。


Download Yelp Kaggle Dataset

您可以使用此数据集进行哪些项目以进行机器学习?

使用NLP和情感分析来找出评论中正面或负面的含义,并推断出各种情感和业务属性的含义。

5)Twitter上的客户支持

Twitter上来自顶级品牌的300万条推文的数据集。


Download Customer Support on Twitter Dataset

我可以使用此ML数据集做什么项目?




机器学习犯罪数据集

1)旧金山犯罪分类

这是一个历史数据集,包含2003年至2015年旧金山地区的12年犯罪报告。数据包括犯罪发生的日期,犯罪时间,犯罪描述,地区,地址,位置坐标和解决方案。

Download San Francisco Crime Classification Dataset

使用犯罪分类Kaggle数据集的ML项目构想

建立端到端机器学习模型,根据事件发生的位置和时间来预测犯罪事件的类别。

2)伦敦犯罪数据集

该数据集由LSOA区,月份和次要/主要类别在2008年1月至2016年12月之间的犯罪报告组成,犯罪记录为1300万行。


Download London Crime Dataset

使用London Crime Kaggle数据集的建议项目

该数据可用于分析根据一周中的某天或某个季节的犯罪发生率是否发生任何变化,或确定特定犯罪在减少或增加的自治市镇。

3)印度犯罪

该数据集包含有关2001年国家犯罪数据的完整信息,分为40多个因素。


Download Crime in India Dataset

使用此数据集的分析建议项目

该数据集可用于分析印度的犯罪模式,例如虐待儿童案件,针对SC和ST的犯罪以及其他犯罪,以根据犯罪模式发现潜在的罪犯。

4)芝加哥犯罪数据集

来自芝加哥警察局的芝加哥犯罪数据集有699万行,具有22个属性。该数据集会随着犯罪事件不断更新。


Download Chicago Crime Dataset

使用Chicago Crime Dataset的机器学习项目构想

可以利用该数据集来构建模型,以分析温度对暴力犯罪(如殴打或殴打)的影响,确定同比增长最高的犯罪类别等。

5)波士顿数据集中的犯罪

数据集由波士顿警察局提供,其中包含2015年6月以来的犯罪类型,犯罪发生的时间和地点,犯罪描述,位置坐标以及其他信息。


Download Crime in Boston Dataset

该数据集可用于构建一个模型,以识别犯罪热点和犯罪的频繁发生时间。


作者 east
python, 人工智能, 数据挖掘 10月 8,2020

python多项式回归代码实现

多项式回归是在上文python源码实现线性回归并绘图

基础上实现的,要实现下面的多项式

可以用矩阵相乘来实现

代码如下:

import numpy as np
import matplotlib.pyplot as plt

# 读入训练数据
train = np.loadtxt('click.csv', delimiter=',', dtype='int', skiprows=1)
train_x = train[:,0]
train_y = train[:,1]

# 标准化
mu = train_x.mean()
sigma = train_x.std()
def standardize(x):
    return (x - mu) / sigma

train_z = standardize(train_x)

# 参数初始化
theta = np.random.rand(3)

# 创建训练数据的矩阵
def to_matrix(x):
    return np.vstack([np.ones(x.size), x, x ** 2]).T

X = to_matrix(train_z)

# 预测函数
def f(x):
    return np.dot(x, theta)

# 目标函数
def E(x, y):
    return 0.5 * np.sum((y - f(x)) ** 2)

# 学习率
ETA = 1e-3

# 误差的差值
diff = 1

# 更新次数
count = 0

# 直到误差的差值小于 0.01 为止,重复参数更新
error = E(X, train_y)
while diff > 1e-2:
    # 更新结果保存到临时变量
    theta = theta - ETA * np.dot(f(X) - train_y, X)

    # 计算与上一次误差的差值
    current_error = E(X, train_y)
    diff = error - current_error
    error = current_error

    # 输出日志
    count += 1
    log = '第 {} 次 : theta = {}, 差值 = {:.4f}'
    print(log.format(count, theta, diff))

# 绘图确认
x = np.linspace(-3, 3, 100)
plt.plot(train_z, train_y, 'o')
plt.plot(x, f(to_matrix(x)))
plt.show()

最后输出效果如下:

作者 east

上一 1 … 4 5 6 下一个

关注公众号“大模型全栈程序员”回复“小程序”获取1000个小程序打包源码。回复”chatgpt”获取免注册可用chatgpt。回复“大数据”获取多本大数据电子书

标签

AIGC AI创作 bert chatgpt github GPT-3 gpt3 GTP-3 hive mysql O2O tensorflow UI控件 不含后台 交流 共享经济 出行 图像 地图定位 外卖 多媒体 娱乐 小程序 布局 带后台完整项目 开源项目 搜索 支付 效率 教育 日历 机器学习 深度学习 物流 用户系统 电商 画图 画布(canvas) 社交 签到 联网 读书 资讯 阅读 预订

官方QQ群

小程序开发群:74052405

大数据开发群: 952493060

近期文章

  • 详解Python当中的pip常用命令
  • AUTOSAR如何在多个供应商交付的配置中避免ARXML不兼容?
  • C++thread pool(线程池)设计应关注哪些扩展性问题?
  • 各类MCAL(Microcontroller Abstraction Layer)如何与AUTOSAR工具链解耦?
  • 如何设计AUTOSAR中的“域控制器”以支持未来扩展?
  • C++ 中避免悬挂引用的企业策略有哪些?
  • 嵌入式电机:如何在低速和高负载状态下保持FOC(Field-Oriented Control)算法的电流控制稳定?
  • C++如何在插件式架构中使用反射实现模块隔离?
  • C++如何追踪内存泄漏(valgrind/ASan等)并定位到业务代码?
  • C++大型系统中如何组织头文件和依赖树?

文章归档

  • 2025年6月
  • 2025年5月
  • 2025年4月
  • 2025年3月
  • 2025年2月
  • 2025年1月
  • 2024年12月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年6月
  • 2024年5月
  • 2024年4月
  • 2024年3月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年1月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年7月
  • 2018年6月

分类目录

  • Android (73)
  • bug清单 (79)
  • C++ (34)
  • Fuchsia (15)
  • php (4)
  • python (43)
  • sklearn (1)
  • 云计算 (20)
  • 人工智能 (61)
    • chatgpt (21)
      • 提示词 (6)
    • Keras (1)
    • Tensorflow (3)
    • 大模型 (1)
    • 智能体 (4)
    • 深度学习 (14)
  • 储能 (44)
  • 前端 (4)
  • 大数据开发 (488)
    • CDH (6)
    • datax (4)
    • doris (30)
    • Elasticsearch (15)
    • Flink (78)
    • flume (7)
    • Hadoop (19)
    • Hbase (23)
    • Hive (40)
    • Impala (2)
    • Java (71)
    • Kafka (10)
    • neo4j (5)
    • shardingsphere (6)
    • solr (5)
    • Spark (99)
    • spring (11)
    • 数据仓库 (9)
    • 数据挖掘 (7)
    • 海豚调度器 (10)
    • 运维 (34)
      • Docker (3)
  • 小游戏代码 (1)
  • 小程序代码 (139)
    • O2O (16)
    • UI控件 (5)
    • 互联网类 (23)
    • 企业类 (6)
    • 地图定位 (9)
    • 多媒体 (6)
    • 工具类 (25)
    • 电商类 (22)
    • 社交 (7)
    • 行业软件 (7)
    • 资讯读书 (11)
  • 嵌入式 (70)
    • autosar (63)
    • RTOS (1)
    • 总线 (1)
  • 开发博客 (16)
    • Harmony (9)
  • 技术架构 (6)
  • 数据库 (32)
    • mongodb (1)
    • mysql (13)
    • pgsql (2)
    • redis (1)
    • tdengine (4)
  • 未分类 (6)
  • 程序员网赚 (20)
    • 广告联盟 (3)
    • 私域流量 (5)
    • 自媒体 (5)
  • 量化投资 (4)
  • 面试 (14)

功能

  • 登录
  • 文章RSS
  • 评论RSS
  • WordPress.org

All Rights Reserved by Gitweixin.本站收集网友上传代码, 如有侵犯版权,请发邮件联系yiyuyos@gmail.com删除.