<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 學習使用編碼器解碼器LSTM循環神經網絡添加數字 > 原文: [https://machinelearningmastery.com/learn-add-numbers-seq2seq-recurrent-neural-networks/](https://machinelearningmastery.com/learn-add-numbers-seq2seq-recurrent-neural-networks/) 長短期記憶(LSTM)網絡是一種循環神經網絡(RNN),能夠學習輸入序列中元素之間的關系。 LSTM的一個很好的演示是學習如何使用諸如和的數學運算將多個項組合在一起并輸出計算結果。 初學者常犯的一個錯誤就是簡單地學習從輸入詞到輸出詞的映射函數。關于這種問題的LSTM的良好演示涉及學習字符的排序輸入(“50 + 11”)和以字符(“61”)預測序列輸出。使用序列到序列或seq2seq(編碼器 - 解碼器),堆疊LSTM配置的LSTM可以學習這個難題。 在本教程中,您將了解如何使用LSTM解決添加隨機生成的整數序列的問題。 完成本教程后,您將了解: * 如何學習輸入項的樸素映射函數來輸出加法項。 * 如何構建添加問題(和類似問題)并適當地編碼輸入和輸出。 * 如何使用seq2seq范例解決真正的序列預測添加問題。 讓我們開始吧。 * **更新Aug / 2018** :修正了模型配置描述中的拼寫錯誤。 ![How to Learn to Add Numbers with seq2seq Recurrent Neural Networks](img/ba6b2b767f7039240f86040b472bd4d2.jpg) 如何學習使用seq2seq循環神經網絡添加數字 照片由 [Lima Pix](https://www.flickr.com/photos/minhocos/11161305703/) ,保留一些權利。 ## 教程概述 本教程分為3個部分;他們是: 1. 添加數字 2. 作為映射問題的添加(初學者的錯誤) 3. 作為seq2seq問題添加 ### 環境 本教程假設安裝了SciPy,NumPy,Pandas的Python 2或Python 3開發環境。 本教程還假設scikit-learn和Keras v2.0 +與Theano或TensorFlow后端一起安裝。 如果您需要有關環境的幫助,請參閱帖子: * [如何使用Anaconda設置用于機器學習和深度學習的Python環境](http://machinelearningmastery.com/setup-python-environment-machine-learning-deep-learning-anaconda/) ## 添加數字 任務是,給定一系列隨機選擇的整數,返回那些整數的總和。 例如,給定10 + 5,模型應輸出15。 該模型將在隨機生成的示例中進行訓練和測試,以便學習添加數字的一般問題,而不是記住特定情況。 ## 作為映射問題添加 (初學者的錯誤) 在本節中,我們將解決問題并使用LSTM解決它,并說明使初學者犯錯誤并且不利用循環神經網絡的能力是多么容易。 ### 數據生成 讓我們首先定義一個函數來生成隨機整數序列及其總和作為訓練和測試數據。 我們可以使用 [randint()](https://docs.python.org/3/library/random.html)函數生成最小值和最大值之間的隨機整數,例如介于1和100之間。然后我們可以對序列求和。該過程可以重復固定次數,以創建數字輸入序列對和匹配的輸出求和值。 例如,此代碼段將創建100個在1到100之間添加2個數字的示例: ```py from random import seed from random import randint seed(1) X, y = list(), list() for i in range(100): in_pattern = [randint(1,100) for _ in range(2)] out_pattern = sum(in_pattern) print(in_pattern, out_pattern) X.append(in_pattern) y.append(out_pattern) ``` 運行該示例將打印每個輸入 - 輸出對。 ```py ... [2, 97] 99 [97, 36] 133 [32, 35] 67 [15, 80] 95 [24, 45] 69 [38, 9] 47 [22, 21] 43 ``` 一旦我們有了模式,我們就可以將列表轉換為NumPy Arrays并重新調整值。我們必須重新調整值以適應LSTM使用的激活范圍。 例如: ```py # format as NumPy arrays X,y = array(X), array(y) # normalize X = X.astype('float') / float(100 * 2) y = y.astype('float') / float(100 * 2) ``` 綜上所述,我們可以定義函數 _random_sum_pairs()_,它接受指定數量的示例,每個序列中的一些整數,以及生成和返回X,y對數據的最大整數造型。 ```py from random import randint from numpy import array # generate examples of random integers and their sum def random_sum_pairs(n_examples, n_numbers, largest): X, y = list(), list() for i in range(n_examples): in_pattern = [randint(1,largest) for _ in range(n_numbers)] out_pattern = sum(in_pattern) X.append(in_pattern) y.append(out_pattern) # format as NumPy arrays X,y = array(X), array(y) # normalize X = X.astype('float') / float(largest * n_numbers) y = y.astype('float') / float(largest * n_numbers) return X, y ``` 我們可能希望稍后反轉數字的重新縮放。這將有助于將預測值與預期值進行比較,并以與原始數據相同的單位獲得錯誤分數的概念。 下面的 _invert()_函數反轉了傳入的預測值和期望值的標準化。 ```py # invert normalization def invert(value, n_numbers, largest): return round(value * float(largest * n_numbers)) ``` ### 配置LSTM 我們現在可以定義一個LSTM來模擬這個問題。 這是一個相對簡單的問題,因此模型不需要非常大。輸入層將需要1個輸入功能和2個時間步長(在添加兩個數字的情況下)。 定義了兩個隱藏的LSTM層,第一個具有6個單元,第二個具有2個單元,接著是完全連接的輸出層,其返回單個總和值。 在給定網絡的實值輸出的情況下,使用有效的ADAM優化算法來擬合模型以及均方誤差損失函數。 ```py # create LSTM model = Sequential() model.add(LSTM(6, input_shape=(n_numbers, 1), return_sequences=True)) model.add(LSTM(6)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') ``` 該網絡適用于100個時期,每個時期生成新的示例,并且在每個批次結束時執行重量更新。 ```py # train LSTM for _ in range(n_epoch): X, y = random_sum_pairs(n_examples, n_numbers, largest) X = X.reshape(n_examples, n_numbers, 1) model.fit(X, y, epochs=1, batch_size=n_batch, verbose=2) ``` ### LSTM評估 我們在100個新模式上評估網絡。 生成這些并且為每個預測總和值。實際和預測的和值都被重新調整到原始范圍,并且計算出具有與原始值相同的比例的均方根誤差(RMSE)分數。最后,列出了約20個預期值和預測值的示例作為示例。 最后,列出了20個預期值和預測值的示例作為示例。 ```py # evaluate on some new patterns X, y = random_sum_pairs(n_examples, n_numbers, largest) X = X.reshape(n_examples, n_numbers, 1) result = model.predict(X, batch_size=n_batch, verbose=0) # calculate error expected = [invert(x, n_numbers, largest) for x in y] predicted = [invert(x, n_numbers, largest) for x in result[:,0]] rmse = sqrt(mean_squared_error(expected, predicted)) print('RMSE: %f' % rmse) # show some examples for i in range(20): error = expected[i] - predicted[i] print('Expected=%d, Predicted=%d (err=%d)' % (expected[i], predicted[i], error)) ``` ## 完整的例子 我們可以將這一切聯系起來。完整的代碼示例如下所示。 ```py from random import seed from random import randint from numpy import array from keras.models import Sequential from keras.layers import Dense from keras.layers import LSTM from math import sqrt from sklearn.metrics import mean_squared_error # generate examples of random integers and their sum def random_sum_pairs(n_examples, n_numbers, largest): X, y = list(), list() for i in range(n_examples): in_pattern = [randint(1,largest) for _ in range(n_numbers)] out_pattern = sum(in_pattern) X.append(in_pattern) y.append(out_pattern) # format as NumPy arrays X,y = array(X), array(y) # normalize X = X.astype('float') / float(largest * n_numbers) y = y.astype('float') / float(largest * n_numbers) return X, y # invert normalization def invert(value, n_numbers, largest): return round(value * float(largest * n_numbers)) # generate training data seed(1) n_examples = 100 n_numbers = 2 largest = 100 # define LSTM configuration n_batch = 1 n_epoch = 100 # create LSTM model = Sequential() model.add(LSTM(10, input_shape=(n_numbers, 1))) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') # train LSTM for _ in range(n_epoch): X, y = random_sum_pairs(n_examples, n_numbers, largest) X = X.reshape(n_examples, n_numbers, 1) model.fit(X, y, epochs=1, batch_size=n_batch, verbose=2) # evaluate on some new patterns X, y = random_sum_pairs(n_examples, n_numbers, largest) X = X.reshape(n_examples, n_numbers, 1) result = model.predict(X, batch_size=n_batch, verbose=0) # calculate error expected = [invert(x, n_numbers, largest) for x in y] predicted = [invert(x, n_numbers, largest) for x in result[:,0]] rmse = sqrt(mean_squared_error(expected, predicted)) print('RMSE: %f' % rmse) # show some examples for i in range(20): error = expected[i] - predicted[i] print('Expected=%d, Predicted=%d (err=%d)' % (expected[i], predicted[i], error)) ``` 運行該示例會在每個時期打印一些損失信息,并通過打印運行的RMSE和一些示例輸出來完成。 結果并不完美,但很多例子都是正確預測的。 鑒于神經網絡的隨機性,您的具體輸出可能會有所不同。 ```py RMSE: 0.565685 Expected=110, Predicted=110 (err=0) Expected=122, Predicted=123 (err=-1) Expected=104, Predicted=104 (err=0) Expected=103, Predicted=103 (err=0) Expected=163, Predicted=163 (err=0) Expected=100, Predicted=100 (err=0) Expected=56, Predicted=57 (err=-1) Expected=61, Predicted=62 (err=-1) Expected=109, Predicted=109 (err=0) Expected=129, Predicted=130 (err=-1) Expected=98, Predicted=98 (err=0) Expected=60, Predicted=61 (err=-1) Expected=66, Predicted=67 (err=-1) Expected=63, Predicted=63 (err=0) Expected=84, Predicted=84 (err=0) Expected=148, Predicted=149 (err=-1) Expected=96, Predicted=96 (err=0) Expected=33, Predicted=34 (err=-1) Expected=75, Predicted=75 (err=0) Expected=64, Predicted=64 (err=0) ``` ### 初學者的錯誤 一切都完成了吧? 錯誤。 我們解決的問題有多個輸入但技術上不是序列預測問題。 實際上,您可以使用多層感知器(MLP)輕松解決它。例如: ```py from random import seed from random import randint from numpy import array from keras.models import Sequential from keras.layers import Dense from keras.layers import LSTM from math import sqrt from sklearn.metrics import mean_squared_error # generate examples of random integers and their sum def random_sum_pairs(n_examples, n_numbers, largest): X, y = list(), list() for i in range(n_examples): in_pattern = [randint(1,largest) for _ in range(n_numbers)] out_pattern = sum(in_pattern) X.append(in_pattern) y.append(out_pattern) # format as NumPy arrays X,y = array(X), array(y) # normalize X = X.astype('float') / float(largest * n_numbers) y = y.astype('float') / float(largest * n_numbers) return X, y # invert normalization def invert(value, n_numbers, largest): return round(value * float(largest * n_numbers)) # generate training data seed(1) n_examples = 100 n_numbers = 2 largest = 100 # define LSTM configuration n_batch = 2 n_epoch = 50 # create LSTM model = Sequential() model.add(Dense(4, input_dim=n_numbers)) model.add(Dense(2)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') # train LSTM for _ in range(n_epoch): X, y = random_sum_pairs(n_examples, n_numbers, largest) model.fit(X, y, epochs=1, batch_size=n_batch, verbose=2) # evaluate on some new patterns X, y = random_sum_pairs(n_examples, n_numbers, largest) result = model.predict(X, batch_size=n_batch, verbose=0) # calculate error expected = [invert(x, n_numbers, largest) for x in y] predicted = [invert(x, n_numbers, largest) for x in result[:,0]] rmse = sqrt(mean_squared_error(expected, predicted)) print('RMSE: %f' % rmse) # show some examples for i in range(20): error = expected[i] - predicted[i] print('Expected=%d, Predicted=%d (err=%d)' % (expected[i], predicted[i], error)) ``` 運行該示例可以完美地解決問題,并且可以在更少的時期內解決問題。 ```py RMSE: 0.000000 Expected=108, Predicted=108 (err=0) Expected=143, Predicted=143 (err=0) Expected=109, Predicted=109 (err=0) Expected=16, Predicted=16 (err=0) Expected=152, Predicted=152 (err=0) Expected=59, Predicted=59 (err=0) Expected=95, Predicted=95 (err=0) Expected=113, Predicted=113 (err=0) Expected=90, Predicted=90 (err=0) Expected=104, Predicted=104 (err=0) Expected=123, Predicted=123 (err=0) Expected=92, Predicted=92 (err=0) Expected=150, Predicted=150 (err=0) Expected=136, Predicted=136 (err=0) Expected=130, Predicted=130 (err=0) Expected=76, Predicted=76 (err=0) Expected=112, Predicted=112 (err=0) Expected=129, Predicted=129 (err=0) Expected=171, Predicted=171 (err=0) Expected=127, Predicted=127 (err=0) ``` 問題是我們將這么多的域編碼到問題中,它將問題從序列預測問題轉變為函數映射問題。 也就是說,輸入的順序不再重要。我們可以按照我們想要的任何方式改變它,并且仍然可以解決問題。 MLP旨在學習映射功能,并且可以輕松解決學習如何添加數字的問題。 一方面,這是一種更好的方法來解決添加數字的具體問題,因為模型更簡單,結果更好。另一方面,它是反復神經網絡的可怕用法。 這是一個初學者的錯誤,我看到在網絡上的許多“ _LSTMs_ ”的介紹中被??復制了。 ## 作為序列預測問題的添加 幀添加的另一種方法使其成為明確的序列預測問題,反過來又使其難以解決。 我們可以將添加框架作為輸入和輸出字符串,讓模型找出字符的含義。整個添加問題可以被構造為一串字符,例如輸出“62”的“12 + 50”,或者更具體地說: * 輸入:['1','2','+','5','0'] * 輸出:['6','2'] 該模型不僅必須學習字符的整數性質,還要學習要執行的數學運算的性質。 注意序列現在如何重要,并且隨機改組輸入將創建一個與輸出序列無關的無意義序列。 還要注意問題如何轉換為同時具有輸入和輸出序列。這稱為序列到序列預測問題,或稱為seq2seq問題。 我們可以通過添加兩個數字來保持簡單,但我們可以看到這可以如何縮放到可變數量的術語和數學運算,可以作為模型的輸入供學習和概括。 請注意,這個形式和本例的其余部分受到了Keras項目中[添加seq2seq示例](https://github.com/fchollet/keras/blob/master/examples/addition_rnn.py)的啟發,盡管我從頭開始重新開發它。 ### Data Generation seq2seq定義問題的數據生成涉及更多。 我們將每件作為獨立功能開發,以便您可以使用它們并了解它們的工作原理。在那里掛。 第一步是生成隨機整數序列及其總和,如前所述,但沒有歸一化。我們可以把它放在一個名為 _random_sum_pairs()_的函數中,如下所示。 ```py from random import seed from random import randint # generate lists of random integers and their sum def random_sum_pairs(n_examples, n_numbers, largest): X, y = list(), list() for i in range(n_examples): in_pattern = [randint(1,largest) for _ in range(n_numbers)] out_pattern = sum(in_pattern) X.append(in_pattern) y.append(out_pattern) return X, y seed(1) n_samples = 1 n_numbers = 2 largest = 10 # generate pairs X, y = random_sum_pairs(n_samples, n_numbers, largest) print(X, y) ``` 僅運行此函數會打印一個在1到10之間添加兩個隨機整數的示例。 ```py [[3, 10]] [13] ``` 下一步是將整數轉換為字符串。輸入字符串的格式為'99 +99',輸出字符串的格式為'99'。 此函數的關鍵是數字填充,以確保每個輸入和輸出序列具有相同的字符數。填充字符應與數據不同,因此模型可以學習忽略它們。在這種情況下,我們使用空格字符填充('')并填充左側的字符串,將信息保存在最右側。 還有其他填充方法,例如單獨填充每個術語。嘗試一下,看看它是否會帶來更好的表現。在下面的評論中報告您的結果。 填充需要我們知道最長序列可能有多長。我們可以通過獲取我們可以生成的最大整數的 _log10()_和該數字的上限來輕松計算這個數,以了解每個數字需要多少個字符。我們將最大數字加1,以確保我們期望3個字符而不是2個字符,用于圓形最大數字的情況,例如200.我們需要添加正確數量的加號。 ```py max_length = n_numbers * ceil(log10(largest+1)) + n_numbers - 1 ``` 在輸出序列上重復類似的過程,當然沒有加號。 ```py max_length = ceil(log10(n_numbers * (largest+1))) ``` 下面的示例添加 _to_string()_函數,并使用單個輸入/輸出對演示其用法。 ```py from random import seed from random import randint from math import ceil from math import log10 # generate lists of random integers and their sum def random_sum_pairs(n_examples, n_numbers, largest): X, y = list(), list() for i in range(n_examples): in_pattern = [randint(1,largest) for _ in range(n_numbers)] out_pattern = sum(in_pattern) X.append(in_pattern) y.append(out_pattern) return X, y # convert data to strings def to_string(X, y, n_numbers, largest): max_length = n_numbers * ceil(log10(largest+1)) + n_numbers - 1 Xstr = list() for pattern in X: strp = '+'.join([str(n) for n in pattern]) strp = ''.join([' ' for _ in range(max_length-len(strp))]) + strp Xstr.append(strp) max_length = ceil(log10(n_numbers * (largest+1))) ystr = list() for pattern in y: strp = str(pattern) strp = ''.join([' ' for _ in range(max_length-len(strp))]) + strp ystr.append(strp) return Xstr, ystr seed(1) n_samples = 1 n_numbers = 2 largest = 10 # generate pairs X, y = random_sum_pairs(n_samples, n_numbers, largest) print(X, y) # convert to strings X, y = to_string(X, y, n_numbers, largest) print(X, y) ``` 運行此示例首先打印整數序列和相同序列的填充字符串表示。 ```py [[3, 10]] [13] [' 3+10'] ['13'] ``` 接下來,我們需要將字符串中的每個字符編碼為整數值。畢竟我們必須處理神經網絡中的數字,而不是字符。 整數編碼將問題轉換為分類問題,其中輸出序列可以被視為具有11個可能值的類輸出。這恰好是具有一些序數關系的整數(前10個類值)。 要執行此編碼,我們必須定義可能出現在字符串編碼中的完整符號字母,如下所示: ```py alphabet = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', ' '] ``` 然后,整數編碼變成了一個簡單的過程,即將字符的查找表構建為整數偏移量,并逐個轉換每個字符串的每個字符。 下面的示例為整數編碼提供了 _integer_encode()_函數,并演示了如何使用它。 ```py from random import seed from random import randint from math import ceil from math import log10 # generate lists of random integers and their sum def random_sum_pairs(n_examples, n_numbers, largest): X, y = list(), list() for i in range(n_examples): in_pattern = [randint(1,largest) for _ in range(n_numbers)] out_pattern = sum(in_pattern) X.append(in_pattern) y.append(out_pattern) return X, y # convert data to strings def to_string(X, y, n_numbers, largest): max_length = n_numbers * ceil(log10(largest+1)) + n_numbers - 1 Xstr = list() for pattern in X: strp = '+'.join([str(n) for n in pattern]) strp = ''.join([' ' for _ in range(max_length-len(strp))]) + strp Xstr.append(strp) max_length = ceil(log10(n_numbers * (largest+1))) ystr = list() for pattern in y: strp = str(pattern) strp = ''.join([' ' for _ in range(max_length-len(strp))]) + strp ystr.append(strp) return Xstr, ystr # integer encode strings def integer_encode(X, y, alphabet): char_to_int = dict((c, i) for i, c in enumerate(alphabet)) Xenc = list() for pattern in X: integer_encoded = [char_to_int[char] for char in pattern] Xenc.append(integer_encoded) yenc = list() for pattern in y: integer_encoded = [char_to_int[char] for char in pattern] yenc.append(integer_encoded) return Xenc, yenc seed(1) n_samples = 1 n_numbers = 2 largest = 10 # generate pairs X, y = random_sum_pairs(n_samples, n_numbers, largest) print(X, y) # convert to strings X, y = to_string(X, y, n_numbers, largest) print(X, y) # integer encode alphabet = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', ' '] X, y = integer_encode(X, y, alphabet) print(X, y) ``` 運行該示例將打印每個字符串編碼模式的整數編碼版本。 我們可以看到空格字符('')用11編碼,三個字符('3')編碼為3,依此類推。 ```py [[3, 10]] [13] [' 3+10'] ['13'] [[11, 3, 10, 1, 0]] [[1, 3]] ``` 下一步是對整數編碼序列進行二進制編碼。 這涉及將每個整數轉換為具有與字母表相同長度的二進制向量,并用1標記特定整數。 例如,0整數表示'0'字符,并且將被編碼為二元向量,其中11元素向量的第0個位置為1:[1,0,0,0,0,0,0,0, 0,0,0,0]。 下面的示例為二進制編碼定義了 _one_hot_encode()_函數,并演示了如何使用它。 ```py from random import seed from random import randint from math import ceil from math import log10 # generate lists of random integers and their sum def random_sum_pairs(n_examples, n_numbers, largest): X, y = list(), list() for i in range(n_examples): in_pattern = [randint(1,largest) for _ in range(n_numbers)] out_pattern = sum(in_pattern) X.append(in_pattern) y.append(out_pattern) return X, y # convert data to strings def to_string(X, y, n_numbers, largest): max_length = n_numbers * ceil(log10(largest+1)) + n_numbers - 1 Xstr = list() for pattern in X: strp = '+'.join([str(n) for n in pattern]) strp = ''.join([' ' for _ in range(max_length-len(strp))]) + strp Xstr.append(strp) max_length = ceil(log10(n_numbers * (largest+1))) ystr = list() for pattern in y: strp = str(pattern) strp = ''.join([' ' for _ in range(max_length-len(strp))]) + strp ystr.append(strp) return Xstr, ystr # integer encode strings def integer_encode(X, y, alphabet): char_to_int = dict((c, i) for i, c in enumerate(alphabet)) Xenc = list() for pattern in X: integer_encoded = [char_to_int[char] for char in pattern] Xenc.append(integer_encoded) yenc = list() for pattern in y: integer_encoded = [char_to_int[char] for char in pattern] yenc.append(integer_encoded) return Xenc, yenc # one hot encode def one_hot_encode(X, y, max_int): Xenc = list() for seq in X: pattern = list() for index in seq: vector = [0 for _ in range(max_int)] vector[index] = 1 pattern.append(vector) Xenc.append(pattern) yenc = list() for seq in y: pattern = list() for index in seq: vector = [0 for _ in range(max_int)] vector[index] = 1 pattern.append(vector) yenc.append(pattern) return Xenc, yenc seed(1) n_samples = 1 n_numbers = 2 largest = 10 # generate pairs X, y = random_sum_pairs(n_samples, n_numbers, largest) print(X, y) # convert to strings X, y = to_string(X, y, n_numbers, largest) print(X, y) # integer encode alphabet = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', ' '] X, y = integer_encode(X, y, alphabet) print(X, y) # one hot encode X, y = one_hot_encode(X, y, len(alphabet)) print(X, y) ``` 運行該示例為每個整數編碼打印二進制編碼序列。 我添加了一些新行,使輸入和輸出二進制編碼更清晰。 您可以看到單個和模式變為5個二進制編碼向量的序列,每個向量具有11個元素。輸出或總和變為2個二進制編碼向量的序列,每個向量再次具有11個元素。 ```py [[3, 10]] [13] [' 3+10'] ['13'] [[11, 3, 10, 1, 0]] [[1, 3]] [[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]] [[[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]]] ``` 我們可以將所有這些步驟綁定到一個名為 _generate_data()_的函數中,如下所示。 ```py # generate an encoded dataset def generate_data(n_samples, n_numbers, largest, alphabet): # generate pairs X, y = random_sum_pairs(n_samples, n_numbers, largest) # convert to strings X, y = to_string(X, y, n_numbers, largest) # integer encode X, y = integer_encode(X, y, alphabet) # one hot encode X, y = one_hot_encode(X, y, len(alphabet)) # return as numpy arrays X, y = array(X), array(y) return X, y ``` 最后,我們需要反轉編碼以將輸出向量轉換回數字,以便我們可以將預期的輸出整數與預測的整數進行比較。 下面的 _invert()_功能執行此操作。關鍵是首先使用 _argmax()_函數將二進制編碼轉換回整數,然后使用整數反向映射到字母表中的字符將整數轉換回字符。 ```py # invert encoding def invert(seq, alphabet): int_to_char = dict((i, c) for i, c in enumerate(alphabet)) strings = list() for pattern in seq: string = int_to_char[argmax(pattern)] strings.append(string) return ''.join(strings) ``` 我們現在擁有為此示例準備數據所需的一切。 注意,這些函數是為這篇文章編寫的,我沒有編寫任何單元測試,也沒有用各種輸入對它們進行戰斗測試。如果您發現或發現明顯的錯誤,請在下面的評論中告訴我。 ### 配置并調整seq2seq LSTM模型 我們現在可以在這個問題上使用LSTM模型。 我們可以認為該模型由兩個關鍵部分組成:編碼器和解碼器。 首先,輸入序列一次向網絡顯示一個編碼字符。我們需要一個編碼級別來學習輸入序列中的步驟之間的關系,并開發這些關系的內部表示。 網絡的輸入(對于兩個數字的情況)是一系列5個編碼字符(每個整數2個,“+”一個),其中每個向量包含11個可能字符的11個特征,序列中的每個項目可能是。 編碼器將使用具有100個單位的單個LSTM隱藏層。 ```py model = Sequential() model.add(LSTM(100, input_shape=(5, 11))) ``` 解碼器必須將輸入序列的學習內部表示轉換為正確的輸出序列。為此,我們將使用具有50個單位的隱藏層LSTM,然后是輸出層。 該問題被定義為需要兩個輸出字符的二進制輸出向量。我們將使用相同的完全連接層(Dense)來輸出每個二進制向量。要兩次使用同一層,我們將它包裝在TimeDistributed()包裝層中。 輸出完全連接層將使用 [softmax激活函數](https://en.wikipedia.org/wiki/Softmax_function)輸出[0,1]范圍內的值。 ```py model.add(LSTM(50, return_sequences=True)) model.add(TimeDistributed(Dense(11, activation='softmax'))) ``` 但是有一個問題。 我們必須將編碼器連接到解碼器,它們不適合。 也就是說,編碼器將為5個向量序列中的每個輸入產生100個輸出的2維矩陣。解碼器是LSTM層,其期望[樣本,時間步長,特征]的3D輸入,以便產生具有2個時間步長的每個具有11個特征的1個樣本的解碼序列。 如果您嘗試將這些碎片強制在一起,則會出現如下錯誤: ```py ValueError: Input 0 is incompatible with layer lstm_2: expected ndim=3, found ndim=2 ``` 正如我們所期望的那樣。 我們可以使用 [RepeatVector](https://keras.io/layers/core/#repeatvector) 層來解決這個問題。該層簡單地重復提供的2D輸入n次以創建3D輸出。 RepeatVector層可以像適配器一樣使用,以將網絡的編碼器和解碼器部分組合在一起。我們可以配置RepeatVector重復輸入2次。這將創建一個3D輸出,包括兩個來自編碼器的序列輸出副本,我們可以使用相同的完全連接層對兩個所需輸出向量中的每一個進行兩次解碼。 ```py model.add(RepeatVector(2)) ``` 該問題被定義為11類的分類問題,因此我們可以優化對數損失( _categorical_crossentropy_ )函數,甚至可以跟蹤每個訓練時期的準確性和損失。 把這些放在一起,我們有: ```py # define LSTM configuration n_batch = 10 n_epoch = 30 # create LSTM model = Sequential() model.add(LSTM(100, input_shape=(n_in_seq_length, n_chars))) model.add(RepeatVector(n_out_seq_length)) model.add(LSTM(50, return_sequences=True)) model.add(TimeDistributed(Dense(n_chars, activation='softmax'))) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) print(model.summary()) # train LSTM for i in range(n_epoch): X, y = generate_data(n_samples, n_numbers, largest, alphabet) print(i) model.fit(X, y, epochs=1, batch_size=n_batch) ``` ### 為什么使用RepeatVector層? 為什么不將編碼器的序列輸出作為解碼器的輸入返回? 也就是說,每個輸入序列時間步長的每個LSTM的一個輸出而不是整個輸入序列的每個LSTM的一個輸出。 ```py model.add(LSTM(100, input_shape=(n_in_seq_length, n_chars), return_sequences=True)) ``` 輸入序列的每個步驟的輸出使解碼器在每個步驟訪問輸入序列的中間表示。這可能有用也可能沒用。在輸入序列的末尾提供最終LSTM輸出可能更符合邏輯,因為它捕獲有關整個輸入序列的信息,準備映射到或計算輸出。 此外,這不會在網絡中留下任何內容來指定除輸入之外的解碼器的大小,為輸入序列的每個時間步長提供一個輸出值(5而不是2)。 您可以將輸出重構為由空格填充的5個字符的序列。網絡將完成比所需更多的工作,并且可能失去編碼器 - 解碼器范例提供的一些壓縮類型能力。試試看吧。 標題為“[”的問題是序列到序列學習嗎?](https://github.com/fchollet/keras/issues/395) “關于Keras GitHub項目提供了一些你可以使用的替代表示的良好討論。 ### 評估LSTM模型 和以前一樣,我們可以生成一批新的示例,并在算法適合后對其進行評估。 我們可以根據預測計算RMSE分數,盡管我在這里為了簡單起見而將其排除在外。 ```py # evaluate on some new patterns X, y = generate_data(n_samples, n_numbers, largest, alphabet) result = model.predict(X, batch_size=n_batch, verbose=0) # calculate error expected = [invert(x, alphabet) for x in y] predicted = [invert(x, alphabet) for x in result] # show some examples for i in range(20): print('Expected=%s, Predicted=%s' % (expected[i], predicted[i])) ``` ### 完整的例子 總而言之,下面列出了完整的示例。 ```py from random import seed from random import randint from numpy import array from math import ceil from math import log10 from math import sqrt from numpy import argmax from keras.models import Sequential from keras.layers import Dense from keras.layers import LSTM from keras.layers import TimeDistributed from keras.layers import RepeatVector # generate lists of random integers and their sum def random_sum_pairs(n_examples, n_numbers, largest): X, y = list(), list() for i in range(n_examples): in_pattern = [randint(1,largest) for _ in range(n_numbers)] out_pattern = sum(in_pattern) X.append(in_pattern) y.append(out_pattern) return X, y # convert data to strings def to_string(X, y, n_numbers, largest): max_length = n_numbers * ceil(log10(largest+1)) + n_numbers - 1 Xstr = list() for pattern in X: strp = '+'.join([str(n) for n in pattern]) strp = ''.join([' ' for _ in range(max_length-len(strp))]) + strp Xstr.append(strp) max_length = ceil(log10(n_numbers * (largest+1))) ystr = list() for pattern in y: strp = str(pattern) strp = ''.join([' ' for _ in range(max_length-len(strp))]) + strp ystr.append(strp) return Xstr, ystr # integer encode strings def integer_encode(X, y, alphabet): char_to_int = dict((c, i) for i, c in enumerate(alphabet)) Xenc = list() for pattern in X: integer_encoded = [char_to_int[char] for char in pattern] Xenc.append(integer_encoded) yenc = list() for pattern in y: integer_encoded = [char_to_int[char] for char in pattern] yenc.append(integer_encoded) return Xenc, yenc # one hot encode def one_hot_encode(X, y, max_int): Xenc = list() for seq in X: pattern = list() for index in seq: vector = [0 for _ in range(max_int)] vector[index] = 1 pattern.append(vector) Xenc.append(pattern) yenc = list() for seq in y: pattern = list() for index in seq: vector = [0 for _ in range(max_int)] vector[index] = 1 pattern.append(vector) yenc.append(pattern) return Xenc, yenc # generate an encoded dataset def generate_data(n_samples, n_numbers, largest, alphabet): # generate pairs X, y = random_sum_pairs(n_samples, n_numbers, largest) # convert to strings X, y = to_string(X, y, n_numbers, largest) # integer encode X, y = integer_encode(X, y, alphabet) # one hot encode X, y = one_hot_encode(X, y, len(alphabet)) # return as numpy arrays X, y = array(X), array(y) return X, y # invert encoding def invert(seq, alphabet): int_to_char = dict((i, c) for i, c in enumerate(alphabet)) strings = list() for pattern in seq: string = int_to_char[argmax(pattern)] strings.append(string) return ''.join(strings) # define dataset seed(1) n_samples = 1000 n_numbers = 2 largest = 10 alphabet = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', ' '] n_chars = len(alphabet) n_in_seq_length = n_numbers * ceil(log10(largest+1)) + n_numbers - 1 n_out_seq_length = ceil(log10(n_numbers * (largest+1))) # define LSTM configuration n_batch = 10 n_epoch = 30 # create LSTM model = Sequential() model.add(LSTM(100, input_shape=(n_in_seq_length, n_chars))) model.add(RepeatVector(n_out_seq_length)) model.add(LSTM(50, return_sequences=True)) model.add(TimeDistributed(Dense(n_chars, activation='softmax'))) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) print(model.summary()) # train LSTM for i in range(n_epoch): X, y = generate_data(n_samples, n_numbers, largest, alphabet) print(i) model.fit(X, y, epochs=1, batch_size=n_batch) # evaluate on some new patterns X, y = generate_data(n_samples, n_numbers, largest, alphabet) result = model.predict(X, batch_size=n_batch, verbose=0) # calculate error expected = [invert(x, alphabet) for x in y] predicted = [invert(x, alphabet) for x in result] # show some examples for i in range(20): print('Expected=%s, Predicted=%s' % (expected[i], predicted[i])) ``` 運行示例幾乎完全符合問題。事實上,運行更多的迭代或增加每個迭代的重量更新( _batch_size = 1_ )會讓你到達那里,但需要10倍的時間來訓練。 我們可以看到預測的結果與我們看到的前20個例子的預期結果相符。 ```py ... Epoch 1/1 1000/1000 [==============================] - 2s - loss: 0.0579 - acc: 0.9940 Expected=13, Predicted=13 Expected=13, Predicted=13 Expected=13, Predicted=13 Expected= 9, Predicted= 9 Expected=11, Predicted=11 Expected=18, Predicted=18 Expected=15, Predicted=15 Expected=14, Predicted=14 Expected= 6, Predicted= 6 Expected=15, Predicted=15 Expected= 9, Predicted= 9 Expected=10, Predicted=10 Expected= 8, Predicted= 8 Expected=14, Predicted=14 Expected=14, Predicted=14 Expected=19, Predicted=19 Expected= 4, Predicted= 4 Expected=13, Predicted=13 Expected= 9, Predicted= 9 Expected=12, Predicted=12 ``` ## 擴展 本節列出了您可能希望探索的本教程的一些自然擴展。 * **整數編碼**。探索問題是否可以單獨使用整數編碼來更好地了解問題。大多數輸入之間的序數關系可能非常有用。 * **變量號**。更改示例以在每個輸入序列上支持可變數量的術語。只要執行足夠的填充,這應該是直截了當的。 * **可變數學運算**。更改示例以改變數學運算,以允許網絡進一步概括。 * **括號**。允許使用括號和其他數學運算。 你嘗試過這些擴展嗎? 在評論中分享您的發現;我很想看到你發現了什么。 ## 進一步閱讀 本節列出了一些可供進一步閱讀的資源以及您可能覺得有用的其他相關示例。 ### 文件 * [神經網絡序列學習](https://arxiv.org/pdf/1409.3215.pdf),2014 [PDF] * [使用RNN編碼器 - 解碼器進行統計機器翻譯的學習短語表示](https://arxiv.org/pdf/1406.1078.pdf),2014 [PDF] * [LSTM可以解決困難的長時滯問題](https://papers.nips.cc/paper/1215-lstm-can-solve-hard-long-time-lag-problems.pdf) [PDF] * [學會執行](https://arxiv.org/pdf/1410.4615.pdf),2014 [PDF] ### 代碼和帖子 * [Keras加法示例](https://github.com/fchollet/keras/blob/master/examples/addition_rnn.py) * [烤寬面條中的加法示例](https://github.com/Lasagne/Lasagne/blob/master/examples/recurrent.py) * [RNN加成(一年級)](http://projects.rajivshah.com/blog/2016/04/05/rnn_addition/)和[筆記本](https://gist.github.com/rajshah4/aa6c67944f4a43a7c9a1204301788e0c) * [任何人都可以學習用Python編寫LSTM-RNN(第1部分:RNN)](https://iamtrask.github.io/2015/11/15/anyone-can-code-lstm/) * [Tensorflow中50行LSTM的簡單實現](https://gist.github.com/nivwusquorum/b18ce332bde37e156034e5d3f60f8a23) ## 摘要 在本教程中,您了解了如何開發LSTM網絡以了解如何使用seq2seq堆疊LSTM范例將隨機整數添加到一起。 具體來說,你學到了: * 如何學習輸入項的樸素映射函數來輸出加法項。 * 如何構建添加問題(和類似問題)并適當地編碼輸入和輸出。 * 如何使用seq2seq范例解決真正的序列預測添加問題。 你有任何問題嗎? 在下面的評論中提出您的問題,我會盡力回答。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看