基於Seq2Seq模型深度學習Github工單

【編者按】Github機器學習開發者Hamel Husain最近寫了一篇詳盡的教程,介紹了如何使用Keras和TensorFlow,基於序列到序列模型從Github工單中提取特徵、總結文本。

難題:訓練模型總結Github工單

矩形框內的為預測

以上結果為隨機選擇所得。請繼續閱讀,下面會有更多結果的鏈接。

動機

我從未想像過自己有一天會使用」神奇」來描述機器學習技術的結果。當我入門深度學習後,這一想法改變了,使用深度學習可以完成諸如識別圖片中的物體和排列兩噸樂高這樣的任務。更令人吃驚的是,你不需要一個博士學位或多年的訓練來釋放這些技術的威力。你只需要會寫代碼,具備高中程度的數學知識,以及耐心。

然而,在業界使用深度學習技術的可復現的例子很匱乏。今天,我將分享一個可復現的、最小可行產品演示如何利用深度學習技術基於文本(Github工單)構建數據產品。

本教程將圍繞如何使用序列到序列模型來總結Github工單中的文本,並展示如下事實:

  • 你不需要使用成噸的算力來達到有意義的結果(我將使用單GPU)。
  • 你不需要編寫很多代碼。令人驚奇的是,寥寥數行代碼就能產生神奇的結果。
  • 即使你不打算總結文本,訓練用於這一任務的模型也可以為其他任務生成特徵。

我將在本文中介紹:

  • 如何收集數據並為深度學習預備數據。
  • 如何創建seq2seq模型的架構並進行訓練。
  • 如何準備模型用於推斷,然後討論、演示多種應用案例。

我的目標聚焦於提供一個端到端的例子,這樣你可以領會工作流的概念模型,而不是鑽研很多數學。我同時也會提供相應的鏈接,以供有興趣的讀者進一步深入。

收集數據

如果你不熟悉Github工單,我強烈建議你在閱讀下面的內容前去看一下Github工單是什麼樣子的。特別地,我們在這個練習中將使用Github工單的正文標題。下面是一個例子:

github.com/scikit-learn/scikit-learn/issues/10458

我們將收集許多對工單標題和工單正文,以便訓練我們的總結工單的模型。基本的思路是看過很多工單描述和標題後,模型可以學習如何總結新的工單。

如果你不在Github工作,獲取Github數據的最佳途徑是使用這個超棒的開源項目,這個項目是這樣描述自己的:

……一個記錄歸檔公開GitHub時間線,使其易於訪問,以供未來分析所用的項目。

從該項目查詢請求數據的指令可以在本文的附錄部分找到。一個機敏的讀者(David Shinn)按照附錄概述的步驟收集了數據,並將本練習所需的數據上傳到了Kaggle!

你可以訪問這個頁面,點擊下載鏈接下載數據。

預備、清洗數據

有時候,清洗數據很不容易。圖片來源:rd.com

Keras文本預處理初步

既然我們已經收集了數據,我們需要為模型準備數據。在轉到代碼之前 ,讓我們溫習下由兩份文檔組成的玩具樣例:

["The quick brown fox jumped over the lazy dog 42 times.", "The dog is lazy"]n

下面是我預處理這一原始文本的大致步驟:

1) 清洗數據 在這一步中,我想移除或替換特定字元,並將所有大寫字元替換為其小寫版本。這一步驟由你自由決定,它取決於數據的多少以及領域細節。在這個玩具樣例中,我將所有大寫字元替換為小寫,並將文本中的數字替換為*number*。在真實的數據中,我將處理更多情況。

["the quick brown fox jumped over the lazy dog *number* times", "the dog is lazy"]n

2) Tokenize 將每份文檔分割為單詞列表:

[[the, quick, brown, fox, jumped, over, the, lazy, dog, *number*, times], [the, dog, is, lazy]]n

3) 構建辭彙表 在你的語料庫中,將每個不同的單詞表示為整數,這意味著你需要創建一個token到整數的映射。此外,我發現為頻率低於特定閾值的罕見單詞保留一個整數,以及為補齊(見下一步驟)保留0很有用。在應用token到整數的映射之後,你的數據可能看起來像這樣:

[[2, 3, 4, 5, 6, 7, 2, 8, 9, 10, 11], [2, 9, 12, 8]]n

4) 對齊 文檔會有不同的長度。在深度學習中,有很多處理這個問題的策略,不過在這個教程中,出於簡單性的考慮,我會補齊、截斷文檔,統一它們的長度。你可以決定在文檔的開始或結尾用零補齊或截斷文檔,這兩者分別稱為「前」和「後」。在前補齊我們的玩具文檔之後,數據可能看起來像這樣:

[[2, 3, 4, 5, 6, 7, 2, 8, 9, 10, 11], [0, 0, 0, 0, 0, 0, 0, 2, 9, 12, 8]]n

決定目標文檔長度的一個合理方法是構建文檔長度的直方圖,然後選擇一個有意義的數字。(注意上面的例子在文檔之前補齊了數據,不過我們也可以在文檔之後補齊。我們會在下一節更多地討論這個。)

準備Github工單數據

我們需要處理的數據看起來是這樣:

包含工單正文和標題的Pandas dataframe

你可以看到,其中包括工單標題和正文,後面我們將分別處理。我在建模時不會使用超鏈接,它們僅供參考。注意,我從原本的5百萬條工單中取樣了2百萬條工單,使這個教程更易於處理。

我個人覺得為深度學習預處理文本數據是極度重複性的工作。Keras有很好的預處理文本數據的工具,不過我希望並行運行這些任務以加快速度。

ktext包

我創建了一個名為ktext的工具,可以進行上一節提到的文本預處理任務。這個庫是keras及其他一些文本處理工具的一層很薄的封裝,利用python的基於進程的多線程進行加速。它同時將所有的預處理步驟連接起來,提供了一些很方便的函數。警告:這個包正在開發之中,所以將其用於本教程以外的任務時要小心(歡迎發起合併請求!)。了解更多這個庫如何工作的信息,可以參閱這篇教程(不過目前而言我建議繼續閱讀本文)。

運行以下代碼處理正文數據:

from ktext.preprocess import processorn# 實例化數據處理對象nbody_pp = processor(keep_n=8000, padding_maxlen=70)n# 處理數據ntrain_body_vecs = body_pp.fit_transform(train_body_raw)n

以上代碼清洗、token化數據,並應用前補齊和後截斷以確保每份文檔的長度為70個單詞。我研究了ktext提供的文檔長度直方圖決定了補齊的長度。此外,我只保留了詞頻最高的8000個辭彙,剩餘辭彙的索引設置為1以代表這是一個罕見詞(這是一個武斷的選擇)。在AWS p3.2xlarge實例(8核、60GB內存)上,運行這些代碼花了1小時。下面的例子顯示了原始數據和處理後的數據的差別:

處理標題的過程差不多:

# 實例化預處理標籤的對象ntitle_pp = processor(append_indicators=True, keep_n=4500, npadding_maxlen=12, padding =post)n# 處理標題ntrain_title_vecs = title_pp.fit_transform(train_title_raw)n

這次,我們傳遞了一些額外的參數:

  • append_indicators=True將在每份文檔的開頭和結尾分別加上_start__end_
  • padding =post意味著零補齊將添加到文檔的結尾,而不是默認的前補齊。

如此處理標題是因為我們希望我們的模型學習預測標題的第一個字母將出現在哪裡,以及片語的結尾應該在哪裡。下一節討論模型架構的時候,這麼做的意義會更明顯。

定義模型架構

圖片來源:knowledge.wharton.upenn.edu

創建神經網路架構就像是搭樂高積木。對初學者而言,將每一層看成API可能會有所幫助:你發給API一些數據,然後API返回一些數據。以這種方式思考問題,你不會被過多知識所壓倒,你可以慢慢地加深你的理解。理解兩個概念很重要:

  • 每層期望的數據的形狀,以及每層將返回的數據的形狀。(當你將許多層堆疊在一起時,輸入和輸出的形狀必須是可兼容的,像樂高一樣)。
  • 在概念上,網路層的輸出表示什麼?堆疊起來的網路層子集的輸出代表了什麼?

想要理解這篇教程,理解上面兩個概念是必要的。如果你不能很好地理解這兩個概念,我強烈建議你先去這個MOOC看一些教學,再回過頭來閱讀本文。

在這篇教程中,我們將利用一個稱為序列到序列(Sequence to Sequence)的網路架構。暫停閱讀本文,仔細閱讀這篇Francois Chollet寫的A ten-minute introduction to sequence-to-sequence learning in Keras(基於Keras10分鐘入門序列到序列學習)。

讀完上面提到的文章之後,你應該能從概念上理解下面的示意圖,一個接受兩個輸入、返回一個輸出的網路:

圖片來源:blog.keras.io

我們即將使用的網路和上面示意圖中的網路很相似:

from keras.models import Modelnfrom keras.layers import Input, LSTM, GRU, Dense, Embedding, Bidirectional, BatchNormalizationnfrom keras import optimizersnn# 隨意設置的嵌入和隱藏單元的潛維度nlatent_dim = 300nn##### 定義模型架構 ######nn########################n#### 編碼器模型 ####nencoder_inputs = Input(shape=(doc_length,), name=Encoder-Input)nn# 編碼器的詞嵌入(工單正文)nx = Embedding(num_encoder_tokens, n latent_dim, n name=Body-Word-Embedding, n mask_zero=False)(encoder_inputs)nnx = BatchNormalization(name=Encoder-Batchnorm-1)(x)nn# 我們不關心`encoder_output`(編碼器輸出),只關心隱藏狀態。n_, state_h = GRU(latent_dim, return_state=True, name=Encoder-Last-GRU)(x)nn# 將編碼器封裝為獨立的實體,n# 這樣,如有必要,我們可以只編碼,不解碼。nencoder_model = Model(inputs=encoder_inputs, n outputs=state_h, n name=Encoder-Model)nnseq2seq_encoder_out = encoder_model(encoder_inputs)nn########################n#### 解碼器模型 ####ndecoder_inputs = Input(shape=(None,), name=Decoder-Input) # teacher forcingnn# 解碼器的詞嵌入 (工單標題)ndec_emb = Embedding(num_decoder_tokens, n latent_dim, n name=Decoder-Word-Embedding, n mask_zero=False)(decoder_inputs)nndec_bn = BatchNormalization(name=Decoder-Batchnorm-1)(dec_emb)nn# 配置解碼器,使用`decoder_state_input`作為初始狀態。ndecoder_gru = GRU(latent_dim, n return_state=True, n return_sequences=True, n name=Decoder-GRU)nndecoder_gru_output, _ = decoder_gru(dec_bn, initial_state=seq2seq_encoder_out)nx = BatchNormalization(name=Decoder-Batchnorm-2)(decoder_gru_output)nn# 用於預測的密集層ndecoder_dense = Dense(num_decoder_tokens, n activation=softmax, n name=Final-Output-Dense)nndecoder_outputs = decoder_dense(x)nn########################n#### Seq2Seq 模型 ####nn#seq2seq_decoder_out = decoder_model([decoder_inputs, seq2seq_encoder_out])nseq2seq_Model = Model([encoder_inputs, decoder_inputs], decoder_outputs)nnnseq2seq_Model.compile(optimizer=optimizers.Nadam(lr=0.001), nloss=sparse_categorical_crossentropy)n

閱讀上面的代碼的時候,你會注意到teacher forcing(教師強制)這個概念。教師強制是一個極為重要的機制,它可以使網路更快地訓練。這篇文章更好地解釋了這一點。

圖片來源:xkcd

【譯者注】圖中的對話為:甲:「這就是你的機器學習系統?」乙:「是呀!你把數據投入到這一大堆線性代數,然後從另一邊收集答案」甲:「如果答案不對會怎麼樣?」乙:「那就攪拌這堆東西直到答案開始變得看起來是對的。」

你也許好奇——我是怎麼想到這些結構的。我從可公開訪問的例子開始,然後進行了很多試驗。上面的xkcd漫畫真的是這一過程的最佳描述。你將注意到我的損失函數是稀疏分類交叉熵而不是分類交叉熵,因為這允許我將整數作為預測的目標,而不是one-hot編碼,這樣更省內存。

訓練模型

轉動隨機梯度下降的曲柄來訓練我們的模型。圖片來源:blogs.northcountrypublicradio.org

訓練模型的代碼相當直截了當,調用我們定義的模型對象的擬合(fit)方法。我們傳遞了一些額外的參數,例如日誌回調、epoch數目、batch尺寸。

下面是我們訓練模型所調用的代碼,以及顯示代碼輸出的markdown文件。

from keras.callbacks import CSVLogger, ModelCheckpointnn# 設置模型日誌的回調nscript_name_base = tutorial_seq2seqncsv_logger = CSVLogger({:}.log.format(script_name_base))nmodel_checkpoint = ModelCheckpoint({:}.epoch{{epoch:02d}}-val{{val_loss:.5f}}.hdf5.format(script_name_base),n save_best_only=True)nn# 傳參至model.fitnbatch_size = 1200nepochs = 7nhistory = seq2seq_Model.fit([encoder_input_data, decoder_input_data], np.expand_dims(decoder_target_data, -1),n batch_size=batch_size,n epochs=epochs,nvalidation_split=0.12, callbacks=[csv_logger, model_checkpoint])n

Train on 1584000 samples, validate on 216000 samplesnEpoch 1/7n1584000/1584000 [================] - 411s 259us/step - nloss: 2.6989 - val_loss: 2.3833nEpoch 2/7n1584000/1584000 [================] - 265s 167us/step - nloss: 2.2941 - val_loss: 2.3035nEpoch 3/7n1584000/1584000 [================] - 264s 167us/step - nloss: 2.2085 - val_loss: 2.2740nEpoch 4/7n1584000/1584000 [================] - 265s 167us/step - nloss: 2.1583 - val_loss: 2.2611nEpoch 5/7n1584000/1584000 [================] - 267s 168us/step - nloss: 2.1226 - val_loss: 2.2555nEpoch 6/7n1584000/1584000 [================] - 265s 167us/step - nloss: 2.0947 - val_loss: 2.2521nEpoch 7/7n1584000/1584000 [================] - 264s 167us/step - nloss: 2.0718 - val_loss: 2.2563n

我在AWS p3.2xlarge實例上訓練了這個模型,訓練7個epoch大概花了35分鐘。在生產環境中,我大概會讓模型訓練更長的事件,並利用額外的回調提前停止訓練或動態調整學習率。不過,我發現上面概述的訓練過程對一個最小可用產品而言已經足夠了。

使用更高級的學習率規劃和架構增強可以帶來顯著的提升,文末的「下一步」一節討論了這方面的內容。

為進行推斷預備模型

圖片來源:wired

為進行推斷(預測)預備模型,我們需要重新組織模型(保持訓練好的權重不變),以便解碼器使用上一個預測作為輸入,而不是接受上一時步的正確答案,如下圖所示:

圖片來源:blog.keras.io

如果你不明白上面一段話,請複習下這篇教程。使用下面的代碼重組解碼器(我寫了很詳見的注釋,以方便你閱讀代碼):

def extract_decoder_model(model):n"""n 從原本的模型中抽取解碼器。nn 輸入:n ------n model: keras模型對象nn 返回:n -------n 一個Keras模型對象,輸入和輸出如下:nn 返回的Keras模型的輸入:n 1: 上一個預測的單詞的詞嵌入索引或<Start>標記n 2: 上一個隱藏狀態,首個單詞時為編碼器的隱藏狀態nn 返回的Keras模型的輸出:n 1. 下一個單詞的預測(類概率)n 2. 解碼器的隱藏狀態,以便在下一時步傳回解碼器作為輸入nn 實現筆記:n ----------------------n 必須提取相關層並重建部分計算圖,以允許不同的輸入,n 因為我們在推斷時不使用教師強制nn """n# 整個架構使用相同的潛維度,n# 因此我們將提取嵌入的潛維度,n# 因為解碼器輸出的潛維度與之相同n latent_dim = model.get_layer(Decoder-Word-Embedding).output_shape[-1]nn# 重建解碼器輸入n decoder_inputs = model.get_layer(Decoder-Input).inputn dec_emb = model.get_layer(Decoder-Word-Embedding)(decoder_inputs)n dec_bn = model.get_layer(Decoder-Batchnorm-1)(dec_emb)nn# 我們在推斷階段不使用教師強制,n# 因此我們不利用編碼器的狀態設置初始值然後不管它,n# 相反,GRU需要具備一個預測的反饋循環,n# 所以我們為這個狀態定義了一個輸入層,這樣我們就可以加上這個功能。n gru_inference_state_input = Input(shape=(latent_dim,), name=hidden_state_input)nn# 我們需要重用權重,這也正是我們編寫這整個函數的原因。n# 如果你檢查我們為訓練創建的解碼器GRU,它會接受兩個tensor作為輸入:n# (1) 用於教師強制的嵌入層輸出,現在這會變為上一步的預測及下一時步的開始n# (2) 狀態,該狀態在第一個時步時基於編碼器初始化,n# 第一次預測之後會重新獲取狀態,並再次傳回 n gru_out, gru_state_out = model.get_layer(Decoder-GRU)([dec_bn, n gru_inference_state_input])nn# 重建密集層n dec_bn2 = model.get_layer(Decoder-Batchnorm-2)(gru_out)n dense_out = model.get_layer(Final-Output-Dense)(dec_bn2)n decoder_model = Model([decoder_inputs, gru_inference_state_input],n[dense_out, gru_state_out])nreturn decoder_modeln

用於預測的更多輔助函數在這個文件中定義。特別地,generate_issue_title(生成工單標題)方法定義了預測工單標題的機制。在這篇教程中,我使用了貪婪下一個最可能單詞方法(greedy next-most-probable word approach)。我會建議你仔細閱讀代碼以完全理解預測是如何做出的。

模型用途演示

圖片來源:starwars.com

1. 開箱即用,總結文本,生成非常出色的demo

在典型的分類和回歸模型中,人們對預測本身不怎麼感興趣,除非附加上大量的可視化和謊言。然而,如果你訓練模型總結自然語言中的文本,預測本身是一個很好的展示方式,向受眾展示你學會了提取有意義的領域特徵——如果同時預測較准,那這看起來就很神奇了。

總結文本的能力本身就可以成為一個有用的數據產品,例如,為用戶自動建議標題。然而,這可能不是這個模型最有用的部分。我們將在下面的小節討論這個模型的其他能力。

文本總結的一些例子(更多例子看這裡):

矩形框內的為預測

2. 提取特徵用於大量任務

回顧下序列到序列模型,它有兩個組件:編碼器和解碼器。編碼器「編碼」信息或從文本中提取特徵,並將信息轉呈解碼器,解碼器接受這些信息,嘗試生成清晰的自然語言總結。

這篇教程中的編碼器為每個工單生成了一個300維向量。這一向量可用於許多機器學習任務,例如:

  • 構建一個推薦系統,查找相似或重複工單
  • 檢測垃圾工單
  • 為預測工單何時關閉的回歸模型提供額外信息
  • 為識別哪些工單表示bug或漏洞的分類器提供額外信息

需要注意的是,從正文文本提取特徵有很多方法,並不保證對某項特定任務而言,這些特徵比用其他方法提取的特徵要優越。我發現將使用這一方法的特徵與其他特徵組合常常有所幫助。然而,我想重點突出的是你通過訓練總結文本的模型免費獲得了這些作為副作用的特徵!

下面展示了實做上面的概念的例子,相似工單建議。由於編碼器提供描述每個工單的300維向量,直截了當的做法就是尋找每個工單在向量空間中的最近鄰。使用annoy包,我在為一些工單生成標題時還展示了最近鄰:

上面兩個例子展示了編碼器提取的特徵如何用於查找語義相似的工單。例如,你可以使用這些特徵給推薦系統或上面提到的其他機器學習任務提供信息。

更激動人心的是,這一切並不僅限於工單。我們可以應用相同的方法基於README文件或代碼的注釋和文檔字元串生成倉庫標題。有無盡的可能性。我在附錄中提供了一些數據,你甚至可以利用這些數據自行進行嘗試。

模型評估

評估文本總結模型表現的一個較好的方法是使用BLEU分數。這裡有為我們的數據生成BLEU分數的代碼。最近的一篇文章使用一些很不錯的可視化出色地解釋了這一指標。我把這留給讀者作練習。

儘管我沒法在這裡分享我最佳模型的BLEU指標,我可以告訴你,我在本文中分享的模型還有顯著的提升空間。我在下一節下一步中給出了一些提示。

下一步

本文的目標是展示Seq2Seq模型如何用於創建有趣的數據產品。我事實上試驗的模型採用了不同的架構,但基本的思路是一樣的。本文沒有提到的一些有用的改進:

  • 增加關注層和雙向RNN。
  • 在編碼器和解碼器上堆疊上更多循環層,並調整許多層的尺寸。
  • 使用正則化(例如:dropout)。
  • 在整個工單語料庫上預訓練詞嵌入。
  • 使用一個更好的token切分演算法,處理混合代碼與文本的問題,以及工單模板與markdown標記的問題。
  • 訓練更多的數據(在這篇教程中,我們只訓練了兩百萬個工單,但其實有更多的數據可供訓練)
  • 使用beam search預測工單標題。
  • 探索基於PyTorch的超級贊的fastai庫,其中包含用於NLP的一些最先進的技術。這涉及從Keras轉到PyTorch。

上面的一些改進是更高級的主題,但學起來並不難。想要學習更多內容的讀者,可以參閱下面的資源一節。

重現我的環境:Nvidia-Docker

為了方便讀者嘗試運行我的代碼,我將所有的依賴打包進了一個Nvidia-Docker容器(使用Nvidia-Docker v1.0,而不是2.0)。不熟悉Docker的讀者可以參考我的另一篇文章。本教程所用的docker鏡像發布在Dockerhub上。

資源

  • 本文的Github倉庫。可以在此查看本文的Juypter Notebook版本。
  • 學習這些概念,我發現投入產出比最高的地方是Jeremy Howard的MOOC fast.ai。MOOC的最新版本中,Jermy使用PyTorch替換了Keras,提供了諸如隨機重啟的周期學習率之類的有用的高層抽象。
  • Francois Chollet的博客,Keras庫的文檔,Keras Github倉庫上的討論。
  • 這個kaggle數據集頁面提供了本文所用到的數據(感謝David Shinn)。如果你想要擴展該數據集,你可以按照附錄所述,通過擴展原始查詢參數收集一個更大的數據集。
  • Airbnb的機器學習科學家Avneesh Saluja在這個出色的演講中討論了他是如何應用一個類似本文所述的方法進行自然語言處理任務的。

感謝

此外,感謝審閱本文並給出寶貴意見的David Shinn、Robert Chang、Zachary Deane-Mayer。

聯繫我

我希望你喜歡這篇文章。歡迎在Twitter、Linkedin、Github上聯繫我。

注意和聲明

本文中包含的任何想法和意見都是我個人的想法和意見。這裡呈現的任何想法和技術並不預示Github未來的產品。

附錄——【可選】如何從頭自行獲取Github工單數據

圖片來源:Jim Holmes,許可:CC BY 2.0

獲取這些數據最簡單的方法是使用BigQuery。當你註冊Google Cloud賬戶時,你會獲贈300美元的額度,遠超獲取本文所用數據所需的金額。如果有機敏的讀者找到更容易的獲取數據的方法,請留言。

我們將仔細參照這個鏈接中的步驟。如果你迷失了方向,可以參考鏈接的文檔。不過我下面將提供具體的步驟:

如果你還沒有Google項目:

  • 登錄Google開發者控制台
  • 創建一個項目並激活BigQuery API

確保你創建的項目連接到你的支付賬戶,以便利用300美元新用戶免費額度(獲取本文的數據花了我4美元)。

完成上述步驟後,你可以進一步請求數據。你可以點擊此鏈接查看請求控制台。在這個頁面,你可以選中右上角的「Query Table」(請求表)按鈕。接著你會看到類似這樣的頁面:

BigQuery 請求編輯器

接著,你需要點擊「Show Options」(顯示選型)按鈕並確保「Legacy SQL」複選框處於未選中狀態(默認選中)。

你會注意到左手邊有項目的名稱,例如GithubIssues。點擊旁邊的藍色下拉菜單(如下圖所示),並選中「Create new dataset」(創建新數據集),為數據集提供一個名字。你會注意到我將數據集起名為github_issues。之後你會用到這個名稱。

現在,我們可以獲取我們想要的數據了!複製粘貼下面的SQL請求到控制台,並點擊紅色的「Run Query」(運行請求)按鈕。作為替代,你也可以點擊這個鏈接。歡迎研究下面的SQL,我們簡單地收集工單的標題和正文,並進行一些數據清洗工作。

SELECTn url as issue_urln-- 將同一行中的連續空白字元替換為單個空格n, REGEXP_REPLACE(title, r"s{2,}", ) as issue_titlen, REGEXP_REPLACE(body, r"s{2,}", ) as bodynnFROM(n SELECTn JSON_EXTRACT(payload, $.issue.html_url) as urln-- 提取標題和正文,移除括弧、方括弧和引號n, LOWER(TRIM(REGEXP_REPLACE(JSON_EXTRACT(payload, $.issue.title), r"n|(|)|[|]|#|*|`|"", ))) as titlen, LOWER(TRIM(REGEXP_REPLACE(JSON_EXTRACT(payload, $.issue.body), r"n|(|)|[|]|#|*|`|"", ))) as bodyn FROM `githubarchive.day.2017*`n WHERE n-- 2017全年 n _TABLE_SUFFIX BETWEEN 0101 and 1231nand type="IssuesEvent" n-- 只需要特定狀態的工單,以避免重複工單nand JSON_EXTRACT(payload, $.action) = ""opened"" n) as tblnnWHERE n-- 正文至少包含8個單詞,標題至少包含3個單詞n-- 這是一個過濾空白或無意義工單的武斷方法n ARRAY_LENGTH(SPLIT(body, )) >= 6nand ARRAY_LENGTH(SPLIT(title, )) >= 3n-- 過濾標題和正文實在太長的工單n-- (這些是離散值,將拖慢切分token的速度)nand LENGTH(title) <= 400nand LENGTH(body) <= 2000 n

上述請求將返回大約5百萬行數據,包含從Github工單提取的(超鏈接, 標題, 正文)信息。你也可以從本文的Github倉庫獲取上面的SQL代碼文件。

請求完成後,你需要將其保存到Google Cloud Bucket,這是一個和Amazon S3類似的服務。為此,你需要點擊請求結果上方的「Save as Table」(作為表保存)按鈕,點擊後,會顯示如下的窗口:

選中「destination dataset」(目標數據集,也就是你之前創建的數據集),然後點擊「OK」。在左面板訪問你剛創建的表,選中藍色的下拉菜單,再選擇「Export Table」(導出表),你會看到這樣的一個對話框:

如果你還沒有創建bucket,你需要點擊「View Files」(查看文件)鏈接以創建bucket。Google Cloud Storage的URL語法如下:

gs://bucket_name/destination_filename.csvn

然而,你需要添加一個通配符,因為數據太大了,無法存儲進單個csv文件中(總共大約有3GB的數據)。比如,我的(私有)bucket的名字是hamel_githubissues,因此我在這裡填寫的路徑是:

gs://hamel_githubissues/*.csvn

一旦你正確進行了上述操作,你會看到表名附近顯示…extracting信息。這隻需要若干分鐘。當這一過程完成後,你可以訪問你的Google Cloud Storage bucket查看你的文件(你會看到類似如下的頁面):

一旦你下載了數據,你將具備完成本教程其他部分所需的一切數據。你可以直接點擊每個文件下載數據,或使用Google Cloud Storage CLI。你甚至可以使用pandas完成整個請求過程。說實話,我決定直接使用用戶界面,因為我平時很少用到Google Cloud。

原文 How To Create Data Products That Are Magical Using Sequence-to-Sequence Models

感謝原作者Hamel Husain授權論智編譯,未經授權禁止轉載。詳情見轉載須知

推薦閱讀:

Udacity 深度學習的作業有人真運行過嗎?
如何評價人們對電腦在圍棋上戰勝人類的時間預測?
深度學習系統相比較傳統的機器學習系統,針對常見的分類問題,精度究竟能有多大提升?
做出「狼人殺」的 AI 有哪些難點?
有沒有非線性版本的 矩陣分解,壓縮感知,稀疏編碼?

TAG:seq2seq | GitHub | 深度学习DeepLearning |