2019年3月19日 星期二

Github for windows clone with Pycharm

  1. 先 google: Github for windows
    https://desktop.github.com/
  2. 點選Download for Windows

    1. 下載後開啟,先登入Github 帳號。

    2. 登入後開啟Pycharm => File => Settings…
    3. 點選 Version Control => Git
      版本控制的Git
    4. 在 path to Git executable 路徑選擇輸入git.exe的路徑
      以我的例子,路徑大概在 C:\Users\Lido_Lee\AppData\Local\GitHubDesktop\app-1.6.5\resources\app\git\cmd\git.exe (這邊依安裝路徑會有不同)
      輸入完後按下"Test" 會告訴你現在Git的版本。
    5. 接著到GitHub 你的Repositories 創建新的Repo.
    6. 填寫Repo.名稱 & 公開還是隱私
    7. 1.點選Clone or downloard => 2.Clone with HTTPS => 3.複製網址
    8. 在Pycharm 中選擇要Clone的資料夾
      1.右鍵=>2.選擇Git =>3.Repository => 4.Clone…
    9. 貼上第8點複製的網址,按下Test,成功會出現綠色Connection successful

      這邊資料夾要是空的才能Clone,Clone好後再將要分享的 jupyternotebook 放進來。
    10. 放進來後,版本控制Git操作就不贅述了。google Git Pycharm 即可。
      後續有空再來update詳細用法。

2019年3月11日 星期一

PyTorch - 基礎 Torch 練習

Torch 本身就是屬於 Tensor 運算的函式庫,其對矩陣處理就如同numpy一樣流利,但Python使用者都很熟悉numpy 了,所以Torch作者也因此做了很方便的功能使得Torch 和Numpy 之間可以互相轉換。
先來試試建立簡單的tensor
import torch
torch.tensor(1,2,3)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-40857d3d51eb> in <module>
----> 1 torch.tensor(1,2,3)

TypeError: tensor() takes 1 positional argument but 3 were given

若要創建tensor 一定要在誇號內加入中誇號[] ,如下:
torch.tensor([1,2,3])
>>>tensor([1, 2, 3])

可見其操作如Numpy一樣簡單
torch.arange(5)
>>>tensor([0, 1, 2, 3, 4])

torch.arange(5).dtype
>>>torch.int64

torch.arange(5.0).dtype
>>>torch.float32

torch.arange(6.0).reshape(2,3)
>>>tensor([[0., 1., 2.],
                  [3., 4., 5.]])

也可以將其轉成numpy的形式:
import numpy as np
a = np.array([1, 2, 3])
t = torch.from_numpy(a)

>>>a
out : array([1, 2, 3])
>>>t
out : tensor([1, 2, 3], dtype=torch.int32)

更多Torch 用法,見官網Doc

來試試處理資料normalization
a = torch.arange(1., 6.)
a_nor = a/torch.mean(a)
a_nor = a/torch.std(a)
a_nor

out : tensor([0.6325, 1.2649, 1.8974, 2.5298, 3.1623])

最後來練習Torch 的梯度
AUTOGRAD: AUTOMATIC DIFFERENTIATION
創建一個 2*2 的矩陣,每個 tensor 值都是1。
x = torch.ones(2, 2, requires_grad=True)
print(x)
out : tensor([[1., 1.],
            [1., 1.]], requires_grad=True)

y = x + 2z = y * y * 3out = z.mean()
print(z, out)
out : tensor([[27., 27.],
            [27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward1>)

out.backward()
print(x.grad)
out : tensor([[4.5000, 4.5000],
            [4.5000, 4.5000]])
不難算出每個tensor 的 梯度值 d(out)/dx 就是 4.5

2019年3月10日 星期日

Pytorch 在 Anaconda windows10 CUDA9 GTX1060 GPU 環境下安裝

  1. 先到pytorch 官網 https://pytorch.org/
  2. 點選 Get start https://pytorch.org/get-started/locally/
    我的python 版本是安裝3.6版的,CUDA 安裝是9.0版,接著複製下面那段文字。
    conda install pytorch torchvision cudatoolkit=9.0 -c pytorch

  3. 開始 =>Anaconda3 => 開起 Anaconda Prompt
    激活先前安裝的環境,我自己的環境名稱為(pypy)
    在prompt 中輸入 $ activate pypy 如下:
    激活環境(pypy)後,再輸入$ conda install pytorch torchvision cudatoolkit=9.0 -c pytorch
  4. 都安裝完後,來測試看看是否正確安裝:

    輸入$ python
    再輸入以下編碼:
    >>> from __future__ import print_function
    >>> import torch
    >>> x = torch.rand(5, 3)
    >>> print(x)

    會得到output如下:
    tensor([[0.0598, 0.0296, 0.2705],
            [0.5359, 0.8694, 0.3644],
            [0.8122, 0.4435, 0.0141],
            [0.7665, 0.4349, 0.3779],
            [0.5709, 0.5939, 0.3551]])
    表示已正確安裝。

  5. 接著就能在我們的IDE下寫段編碼測試測試
    import torch
    x = torch.rand(5, 3)
    print(x)

    >>>tensor([[0.3140, 0.0046, 0.6260],
                     [0.1289, 0.4955, 0.4758],
                     [0.1680, 0.4328, 0.9986],
                     [0.5861, 0.3964, 0.8033],
                     [0.9430, 0.3704, 0.5186]])

2019年3月5日 星期二

深度學習 - LSTM生成文本 - 唐詩 - 生成唐詩

深度學習 - LSTM生成文本 - 唐詩 - 生成唐詩

最後,我們利用訓練好的模型來生成唐詩。
以下函式def function 通通寫在class PoetryModel(object): 底下。
import 所用到的庫
import random import os import keras import numpy as np from keras.callbacks import LambdaCallback from keras.models import Input, Model, load_model from keras.layers import LSTM, Dropout, Dense from keras.optimizers import Adam from data_utils import * from config import Config
class PoetryModel(object):
與先前練習的差不多,也是加入softmax temperature 參數,使得在不同溫度的情況下,模型產生出得文章會有不同的創造力。
這邊與先前不同的是,這裡使用np.power,是冪次函數,而先前練習的是指數函數。不過都是利用加入 temperature 參數,使得預測的文字具有創造性。
#給定模型預測,採樣下一個字符的函數 def sample(self, preds, temperature=1.0): ''' 當temperature=1.0時,模型輸出正常 當temperature=0.5時,模型輸出比較open 當temperature=1.5時,模型輸出比較保守 在訓練的過程中可以看到temperature不同,結果也不同 就是一個概率分佈變換的問題,保守的時候概率大的值變得更大,選擇的可能性也更大 ''' preds = np.asarray(preds).astype('float64') exp_preds = np.power(preds,1./temperature) preds = exp_preds / np.sum(exp_preds) pro = np.random.choice(range(len(preds)),1,p=preds) return int(pro.squeeze())
再來,將預測文字的函數先寫好,供class內部使用。
#根據一串輸入,返回單個預測字符 def _pred(self,sentence,temperature =1): '''因為模型是用 max_len 長度輸入訓練,預測下個字符。 所以要排除輸入一串文字小於 max_len 的情況''' if len(sentence) < self.config.max_len: print('in def _pred,length error ') return '''輸入字串向量化,丟入模型預測''' sentence = sentence[-self.config.max_len:] x_pred = np.zeros((1, self.config.max_len, len(self.words))) for t, char in enumerate(sentence): x_pred[0, t, self.word2numF(char)] = 1. preds = self.model.predict(x_pred, verbose=0)[0] next_index = self.sample(preds,temperature=temperature) #輸出再由向量轉回文字 next_char = self.num2word[next_index] return next_char def _preds(self,sentence,length = 23,temperature =1): '''sentence:預測輸入值;lenth:預測出的字符串長度; 供 class 內部調用,輸入max_len長度字符串, 返回length長度的預測值字符串''' sentence = sentence[:self.config.max_len] generate = '' for i in range(length): pred = self._pred(sentence,temperature) generate += pred sentence = sentence[1:]+pred return generate
以上寫好後,就可以來試著生成唐詩。
先練習最基本的,如同訓練時給前六個字,預測下一個字,一直迴圈到預測整首詩。
'''根據給出的前max_len個字,生成詩句''' def predict_sen(self, text,temperature =1): '''此例中,即根據給出的第一句詩句(含逗號),來生成古詩''' if not self.model: return max_len = self.config.max_len if len(text) < max_len: print('length should not be less than ', max_len) #排除輸入一串文字長度小於 max_len 的情況 return sentence = text[-max_len:] # print('the first line:',sentence) generate = str(sentence) generate += self._preds(sentence,length = 24-max_len,temperature=temperature) return generate
我們試試以下練習:給三種溫度看看輸出。
for temperature in [0.5, 1, 1.5]: poetry1 = model.predict_sen("柯批好市長,",temperature = 1.5) print(poetry1)
柯批好市長,丹齣天杯上。齣南門荷春,將對愁華馬。
柯批好市長,新間與照想。還為碧茲陵,親國葉白上。
柯批好市長,飛坐孤何平。氣還還高得,竹時相州過。
呵,還蠻有趣的!
接著試試看隨機選一首詩的開頭,當作輸入會不會讓模型寫的詩好看一些?
def predict_random(self,temperature = 1): '''隨機從庫中選取一句開頭的詩句,生成五言絕句''' if not self.model: print('model not loaded') return index = random.randint(0, self.poems_num) sentence = self.poems[index][: self.config.max_len] generate = self.predict_sen(sentence,temperature=temperature) return generate
for temperature in [0.5, 1, 1.5]: poetry_Random = model.predict_random(temperature = temperature) print(poetry_Random)
午醉醒來晚,人日何雲從。花日池東見,林同無下得。
何處鞦風至,流鍾虛日北。有月吾間人,吹臨早相連。
流品是鴛鴦,遠長夜十四。愛時來齣何,今方空石意。
原詩為:
午醉醒來晚,無人夢自驚。夕陽如有意,長傍小窗明。
何處鞦風至,蕭蕭送雁群。朝來入庭樹,孤客最先聞。
流品是鴛鴦,翻飛雲水鄉。風高離極浦,煙暝下方塘。比鷺行藏彆,穿荷羽翼香。雙雙浴輕浪,誰見在瀟湘。
若不知原詩為何,模型寫的以假亂真,真是難以想像。今天要是寫給外國人看,可能真的會相信呢!!
接著來玩玩藏頭詩,我們要將想藏頭的字串,逐個丟進max_len的最後一個字然後丟進模型預測下一個字,直至完整的詩句。此例為四字藏頭,如下:
'''根據給4個藏頭字,生成藏頭詩五言絕句''' def predict_hide(self, text,temperature = 1): if not self.model: print('model not loaded') return if len(text)!=4: print('藏頭詩的輸入必須是4個字!') return #選取隨機一首詩的最後(max_len-1)個字符(含句號)+給出的首個文字作為初始輸入 ex.前明月光。+text[0] (共6個字) #此練習輸入共6個字,同訓練模型時的條件。 index = random.randint(0, self.poems_num) sentence = self.poems[index][-self.config.max_len:-1] + text[0] generate = str(text[0]) print('first line = ',sentence) #給出藏頭詩後五個字(含逗號) for i in range(5): next_char = self._pred(sentence,temperature) sentence = sentence[1:] + next_char generate+= next_char #將藏頭詩的第二個字以後加入 for i in range(3): generate += text[i+1] sentence = sentence[1:] + text[i+1] #完成後面每個藏頭詩的句子 for i in range(5): next_char = self._pred(sentence,temperature) sentence = sentence[1:] + next_char generate+= next_char return generate
藏頭詩的藏頭"華碩石頭",丟進模型看看:
for temperature in [0.5, 1, 1.5]: hide_poetry = model.predict_hide('華碩石頭', temperature = temperature) print(hide_poetry)
first line =  意在浮花。華
華見不心故,碩道一水久。石人天關子,頭是花如鞦。
first line =  欲媚濃妝。華
華度曉可堂,碩長颱欲帝。石是青長待,頭驚齣朝相。
first line =  應在十洲。華
華清東色齊,碩王虎月顔。石山在逢歸,頭道公林共。
只給模型第一個字,完成整個詩(共24個字,含逗號、句號)
'''根據給出的首個文字,生成五言絕句''' def predict_first(self, char,temperature =1): if not self.model: print('model not loaded') return index = random.randint(0, self.poems_num) #選取隨機一首詩的最後max_len個字符+給出的首個文字作為初始輸入 sentence = self.poems[index][-self.config.max_len:-1] + char generate = str(char) # print('first line = ',sentence) # 直接預測後面23個字符 generate += self._preds(sentence,length=23,temperature=temperature) return generate
for temperature in [0.5, 1, 1.5]: poetry_first = model.predict_first("中", temperature = temperature) print(poetry_first)
中來不故君,在林中雨有。夜新月山時,聞傢誰歸空。
中平知世相,見可微得西。清城有意齣,裏正君相風。
中望微翻草,常月玉雪外。木州颱水上,林所州上願。
以上都是參考作者的編碼做練習,以下我也來利用一下 predict_first 做為內部調用,寫一個函式,把每一首詩的開頭當作藏頭,想輸入多少字,就有幾首詩:
'''每一首詩的開頭當作藏頭,想輸入多少字,就有幾首詩''' def hide_poetry(self,text,temperature = 1,): generate = '' for i in text: sen = model.predict_first(i,temperature) generate += sen +"\n" return generate
for temperature in [0.5, 1, 1.5]: hide_poetry = model.hide_poetry("花好月圓") print("temperature : %s" %temperature) print(hide_poetry)
temperature : 0.5
花期雲曉照,鍾發上傢月。為中水城子,門願為期宿。
好今君裏蒼,樓傢復地同。群春事人多,相重山中東。
月寒空中山,且成往當一。與為君不色,中過清待外。
圓行誰陽不,國衣有山吹。華二光歸安,客夜東中春。

temperature : 1
花吳天欲水,去見今閣詩。軒惜相子得,寄聞寒高荷。
好為山滿陵,雲有香春攀。不高彆待容,知名作人殊。
月恩安帶葉,期山倚王寒。君為州上長,已長藏朝莫。
圓裏子來三,散風馀關對。君雲鞦人著,為不遲水正。

temperature : 1.5
花當未已是,中持老日門。窗不已韆在,居眾夜彆恩。
好憶天上驚,聲對朝發日。風已空來罷,樹裏煙草鳥。
月春露應清,起金閑水平。來寒起前不,晚愛前何不。
圓夜為正暮,時齣堪海池。終幾亦落思,隱颱林山白。
用AI寫詩,還蠻有趣的!! 雖然不能寫出有押韻的詩,但模型還是能寫出有模有樣的句子。
神經網絡已經可以記住逗號、句號出現在詩中的位置,且詩句都很假掰,很有詩的味道。
LSTM 模型的練習還有很多,可以應用面很廣,算是 NLP 領域的入門,身為初學者一定要好好練習。

2019年3月3日 星期日

深度學習 - LSTM生成文本 - 唐詩 - 訓練模型

經過文本預處理之後,就要將文本批次丟進模型裡面訓練。
這邊直接使用作者 youyuge34 的編碼 來練習。
在根目錄底下的檔案結構:
poetry_model 為訓練 model 代碼: 如下:
會用到的函式庫
import random import os import keras import numpy as np from keras.callbacks import LambdaCallback from keras.models import Input, Model, load_model from keras.layers import LSTM, Dropout, Dense from keras.optimizers import Adam from data_utils import * from config import Config
首先,先看整個模型class:
class PoetryModel(object): def __init__(self, config): self.model = None self.do_train = True self.loaded_model = True self.config = config # 文件預處理 self.word2numF, self.num2word, self.words, self.files_content = preprocess_file(self.config) # 詩的list self.poems = self.files_content.split(']') # 詩的總數量 self.poems_num = len(self.poems) # 如果模型檔案存在(已訓練好)則直接加載模型,否則開始訓練 if os.path.exists(self.config.weight_file) and self.loaded_model: self.model = load_model(self.config.weight_file) else: self.train()
其中幾個小細節:
__init__:有種初始化這個 class 的概念。在 Python 腳本語言中非常常用。這邊將後續會用到的 function 都先定義好,方便之後調用。
文件預處理在上一篇中已經將其寫成函數存成檔案 data_utils.py,可以import 後直接調用 preprocess_file(Config)。另外訓練模型的部分,如果模型已訓練好可以直接調用,不用再重新訓練。
建立模型:使用API 方式建立,兩層 LSTM 搭配 Dropout
def build_model(self): "建立模型" print('building model') # 輸入的dimension input_tensor = Input(shape=(self.config.max_len, len(self.words))) lstm = LSTM(512, return_sequences=True)(input_tensor) dropout = Dropout(0.6)(lstm) lstm = LSTM(256)(dropout) dropout = Dropout(0.6)(lstm) dense = Dense(len(self.words), activation='softmax')(dropout) #model definition self.model = Model(inputs=input_tensor, outputs=dense) #determine optimizer optimizer = Adam(lr=self.config.learning_rate) self.model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])
文本生成器:
定義max_len=6,在生成器中我們取前六個字,讓模型預測第七個字
所以x是文本的前六個字,y是第七個字,然後將其轉換成one-hot編碼。
def data_generator(self): "生成器生成數據" i = 0 while 1: x = self.files_content[i: i + self.config.max_len] y = self.files_content[i + self.config.max_len] if ']' in x or ']' in y: i += 1 continue y_vec = np.zeros( shape=(1, len(self.words)), dtype=np.bool ) y_vec[0, self.word2numF(y)] = 1.0 x_vec = np.zeros( shape=(1, self.config.max_len, len(self.words)), dtype=np.bool ) for t, char in enumerate(x): x_vec[0, t, self.word2numF(char)] = 1.0 yield x_vec, y_vec i += 1
訓練模型:
def train(self): "訓練模型" print('training') number_of_epoch = len(self.files_content)-(self.config.max_len + 1)*self.poems_num number_of_epoch /= self.config.batch_size number_of_epoch = int(number_of_epoch / 1.5) print('epoches = ',number_of_epoch) print('poems_num = ',self.poems_num) print('len(self.files_content) = ',len(self.files_content)) if not self.model: self.build_model() self.model.fit_generator( generator=self.data_generator(), verbose=True, steps_per_epoch=self.config.batch_size, epochs=number_of_epoch, callbacks=[ keras.callbacks.ModelCheckpoint(self.config.weight_file, save_weights_only=False), #LambdaCallback(on_epoch_end=self.generate_sample_result) ] )
最後,我們開始訓練模型:
PoetryModel(Config)
大概跑9小時多,就完成了33415個 epochs。