DataWhaleチームパンチ学習キャンプtask02-2

言語モデルとデータ収集

言語モデル
の自然言語テキストは長さを考えると、離散時系列として見ることができるための
単語の順序
:すなわちシーケンス確率計算、ターゲット言語モデルは、シーケンスの妥当性を評価することで、
ここに画像を挿入説明
このセクションでは、統計に基づいて紹介言語モデル、主に
グラム(
-gram)。以降のセクションでは、ニューラルネットワークに基づく言語モデルをご紹介します。

言語モデルの
仮定シーケンスW1、W2、...、WT生成順番に各単語、私たちがしている
ここに画像を挿入説明
、たとえば、4つの単語を含むテキストのシーケンスの確率
ここに画像を挿入説明
確率パラメータは、言語モデルの単語であり、第1のいくつかの単語を与えられました確率の場合の条件。トレーニングデータセットは、このような全てのWikipediaのエントリの確率として大きなテキストコーパスとして提供され、単語は、トレーニングデータに用語によって計算することができる相対的な単語の頻度を設定し、例えば、
確率は、のように計算することができる:
ここに画像を挿入説明
ここで、n(W1)コーパスの番号は、テキストの最初の単語とW1、N中国語のこのコーパスの総数です。
:同様に、条件付き確率であるW2 W1は、のように計算することができる場合、所与の
ここに画像を挿入説明
テキストの単語の第二の数として第1ワードW1とコーパス、W2通りであるN-(W1、W2)。

nグラム
系列長が増加すると、単語の共起確率を複数算出し、記憶の複雑さが指数関数的に増加します。N-gramモデルは、n = 1の場合、次に、ワードのみ表示され、N前方に関連付けられた単語、すなわち、n次マルコフ連鎖(n次のマルコフ連鎖)はマルコフマルコフ仮定手段を仮定することによって単純化されますそこにP(W3 | W1、W2) = P(W3 | W2)。:N-1次マルコフ連鎖に基づいて、我々は言語モデル書き換えることができ
ここに画像を挿入説明
、上記とも呼ばれるnグラム(nグラム)、確率言語モデルのn-1次マルコフ連鎖です。例えば、テキスト・シーケンスの確率は、4つの言葉のように書き換えることができる含まれている場合はn = 2:
ここに画像を挿入説明
それぞれ、ここでnは1、2、および3、それぞれ1元構文(ユニグラム)と呼ぶ、でバイグラムのバイグラム( )と三元構文(トライグラム)。例えば、配列の長さは4、W2、W3、W4グラムをW1、及びバイグラム確率は三構文です。
ここに画像を挿入説明

nが小さい場合には、nグラムは、多くの場合、正確ではありません。例えば、グラム、3ワードの文章は同じである「あなたが最初に行く」「あなたが最初に行く」と確率です。大きい場合、Nしかし、nグラムは、マルチワードの単語頻度と隣接周波数の多数を計算し記憶しておく必要があります。

思考:
グラム可能な欠陥は何ですか?

1.パラメータ空間は大きすぎる
2.スパースデータ

言語モデル・データ・セット

データセットを読みます

with open('/home/kesci/input/jaychou_lyrics4703/jaychou_lyrics.txt') as f:
    corpus_chars = f.read()
print(len(corpus_chars))
print(corpus_chars[: 40])
corpus_chars = corpus_chars.replace('\n', ' ').replace('\r', ' ')
corpus_chars = corpus_chars[: 10000]

63282
ヘリコプターを持ちたい
とあなたが宇宙に飛びたいが、
あなたが一緒に溶融したい
宇宙の中でとろける、
私は毎日毎日午前

ビルド文字インデックス

idx_to_char = list(set(corpus_chars)) # 去重,得到索引到字符的映射
char_to_idx = {char: i for i, char in enumerate(idx_to_char)} # 字符到索引的映射
vocab_size = len(char_to_idx)
print(vocab_size)

corpus_indices = [char_to_idx[char] for char in corpus_chars]  # 将每个字符转化为索引,得到一个索引的序列
sample = corpus_indices[: 20]
print('chars:', ''.join([idx_to_char[idx] for idx in sample]))
print('indices:', sample)

1027の
文字:あなたがヘリコプターを持っているし、あなたが行くとしたいしたい宇宙に飛びたい
インデックス:[1022、648、1025 、366、208、792、199、1022、648、641、607、625、26、155、130 、5、199、1022、648、641]

次のセクションで直接呼び出される関数のload_data_jay_lyricsを、定義されました。

def load_data_jay_lyrics():
    with open('/home/kesci/input/jaychou_lyrics4703/jaychou_lyrics.txt') as f:
        corpus_chars = f.read()
    corpus_chars = corpus_chars.replace('\n', ' ').replace('\r', ' ')
    corpus_chars = corpus_chars[0:10000]
    idx_to_char = list(set(corpus_chars))
    char_to_idx = dict([(char, i) for i, char in enumerate(idx_to_char)])
    vocab_size = len(char_to_idx)
    corpus_indices = [char_to_idx[char] for char in corpus_chars]
    return corpus_indices, char_to_idx, idx_to_char, vocab_size

データのサンプリングタイミング
毎回のトレーニングでは、我々は、サンプルとランダム読み取りラベルの少量を必要とします。データサンプルのタイミングは、典型的には、連続した文字を含むこと以外は前のセクションとの実験データ。サンプルシーケンスは、「持っている」「すべきである」、「ストレート」、「考える」、であること、5つの文字で、時間ステップの数が5であると仮定すると、「L。」トレーニングセットのサンプルにタグ配列を持っている、「持っている」、「ストレート」、「アップ」、「機械」、すなわち、Xは=「ヘリコプターを持ちたい」、Y =」「を」次の文字、つまり、の文字ですヘリコプター。 "

:私たちは今、時間ステップの数が5であれば、次のようにサンプリングし、ラベルも、「ヘリコプターを持ちたい、とあなたは宇宙に飛びたい」シーケンスを考える
ここに画像を挿入説明
あなたが見ることができ、シーケンス番号Tの長さは、時間ステップである場合nは、重複の多くを持って、その後Tnの合法的なサンプルの合計が、これらのサンプルを、我々は通常、より効率的なサンプリング方法を使用します。私たちは、時系列データのサンプリングの2つの方法があり、ランダムサンプリングと隣接するサンプリングがあります。

ランダムにサンプリングされた
次のコードは、毎回、少量のデータのランダムサンプリングを。バッチサイズはBATCH_SIZE少量当たりのサンプルの数であり、工程数に含まれる各サンプル時間をnum_steps。ランダムサンプリングでは、各サンプルは、必ずしも隣接していない元の配列に隣接する2つの少量のランダムな位置のシーケンスの元の順序で行われます。

import torch
import random
def data_iter_random(corpus_indices, batch_size, num_steps, device=None):
    # 减1是因为对于长度为n的序列,X最多只有包含其中的前n - 1个字符
    num_examples = (len(corpus_indices) - 1) // num_steps  # 下取整,得到不重叠情况下的样本个数
    example_indices = [i * num_steps for i in range(num_examples)]  # 每个样本的第一个字符在corpus_indices中的下标
    random.shuffle(example_indices)

    def _data(i):
        # 返回从i开始的长为num_steps的序列
        return corpus_indices[i: i + num_steps]
    if device is None:
        device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    
    for i in range(0, num_examples, batch_size):
        # 每次选出batch_size个随机样本
        batch_indices = example_indices[i: i + batch_size]  # 当前batch的各个样本的首字符的下标
        X = [_data(j) for j in batch_indices]
        Y = [_data(j + 1) for j in batch_indices]
        yield torch.tensor(X, device=device), torch.tensor(Y, device=device)

試験この関数、我々は人工的な配列として0から29までの連続する整数を入力し、時間の提供バッチサイズ及び数は、それぞれ、2及び6ステップ、入力Xとラベルを無作為にサンプリング印字毎に試料の少量を読み取るY.

my_seq = list(range(30))
for X, Y in data_iter_random(my_seq, batch_size=2, num_steps=6):
    print('X: ', X, '\nY:', Y, '\n')

X:テンソル([[6、7、8、9、10、11]、
[12、13、14、15、16、17]])
Y:テンソル([7、8、9、10、11、 12]、
[13、14、15、16、17、18]])

X:テンソル([0、1、2、3、4、5]、
[18、19、20、21、22、23]])
Y:テンソル([[1、2、3、4、5、 6]、
[19、20、21、22、23、24]])

隣接するサンプル
隣接サンプリングで、元の配列に隣接して少量に隣接する2つのランダムな位置。

def data_iter_consecutive(corpus_indices, batch_size, num_steps, device=None):
    if device is None:
        device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    corpus_len = len(corpus_indices) // batch_size * batch_size  # 保留下来的序列的长度
    corpus_indices = corpus_indices[: corpus_len]  # 仅保留前corpus_len个字符
    indices = torch.tensor(corpus_indices, device=device)
    indices = indices.view(batch_size, -1)  # resize成(batch_size, )
    batch_num = (indices.shape[1] - 1) // num_steps
    for i in range(batch_num):
        i = i * num_steps
        X = indices[:, i: i + num_steps]
        Y = indices[:, i + 1: i + num_steps + 1]
        yield X, Y

同じ設定の下で、入力Xと各リードの少量の隣接ラベル試料のサンプルを印刷Y. 元の配列に隣接するランダム少量上の2つの隣接する位置。

for X, Y in data_iter_consecutive(my_seq, batch_size=2, num_steps=6):
    print('X: ', X, '\nY:', Y, '\n')

X:テンソル([0、1、2、3、4、5]、
[15、16、17、18、19、20]])
Y:テンソル([[1、2、3、4、5、 6]、
[16、17、18、19、20、21]])

X:テンソル([[6、7、8、9、10、11]、
[21、22、23、24、25、26]])
Y:テンソル([7、8、9、10、11、 12]、
[22、23、24、25、26、27]])

公開された31元の記事 ウォンの賞賛0 ビュー809

おすすめ

転載: blog.csdn.net/qq_44750620/article/details/104315517