學習筆記TF021:預測編碼、字元級語言建模、ArXiv摘要
預測編碼(predictive coding),向RNN輸入大量序列,訓練預測序列下一幀能力。語言建模(language modelling),預測一個句子中下一個單詞的似然。生成文本,依據網路下一個單詞分布抽樣,訓練結束,種子單詞(seed word)送入RNN,觀察預測的下一個單詞,最可能單詞輸入RNN,重複,生成新內容。預測編碼壓縮訓練網路任意序列所有重要信息。網路捕捉語法、語言規則,精確預測是語言下一個字元。
字元級語言建模,網路不僅學會構詞,還學會拼寫,網路輸入維數更低,不必考慮未知單詞,可以發明新單詞。Andrew Karpathy 2015年應用RNN於字元級語言建模。https://github.com/karpathy/char-rnn 。
ArXiv.org託管計算機科學、數學、物理學、生物學等領域研究論文。提供基於Web可檢索文獻API。
依據給定搜索查詢從ArXiv獲取摘要,在構造方法,檢查是否有舊摘要轉儲文件。有,直接使用,不調ArXiv API。執行新查詢,刪除或轉移舊轉儲文件。可以優化檢查已有文件與新類別、新關鍵詞是否匹配。沒有轉儲文件,調_fetch_all,生成行寫入磁碟。
只在Machine Learning、Neural and Evolutionary Computing、Optimization and Control,搜索機器學習論文。只返回包含單詞neural、network、deep元數據結果。
_fetch_all完成分頁。每次查詢,返回定量摘要,指定偏移量獲到指定頁結果。_fetch_page傳入指定頁面尺寸參數。參數很大,嘗試一次性得到全部結果,嚴重影響查詢效率。頁面獲取容錯性更強,減小ArXiv API負載。
抓取結果XML格式,BeautifulSoup庫提取摘要。執行命令 sudo -H pip3 install beautifulsoup4 安裝。查看文章 標籤,讀取標籤摘要文本。
定義任務,編寫解析器獲取數據集。預測編碼模型,預測輸入序列下一個字元,只有一個輸入,構造方法sequence參數。參數對象,修改重要選項,復現實驗。initial參數,默認值None,循環連接層初始內部活性值。TensorFlow隱狀態初始化為零張量,語言模型採樣時需要再定義。
數據處理,構造辦玫數據、目標序列,引入時域差。時間步t,St輸入,St+1輸出。提供序列切片,切除第一幀或最後一幀。tf.slice切片運算,參數序列、各維起始索引元組、各維大小元組。sizes-1保持維度起始索引到終止索引所有元素不變。只關心第2維。
mask,尺寸batch_size*max_length張量,分量非0即1,取決幀是否被使用。屬性length沿時間軸對mask求和,得到每個序列長度。mask、length屬性對數據序列合法,與目標序列長度相同,不在數據序列上計算,包含最後一幀,沒有下一字母可預測。數據張量最後一幀切除,包含填序幀,不包含大多數序列實際最後一幀。用mask對代價函數掩膜處理。
同時獲得預測和最後循環活性值。之前僅返回預測值。最後活性值有效生成序列。forward返回兩個張量元組,prediction、state只是方便外部訪問。
每個時間步,模型從辭彙表預測下一字母。分類問題,採用交叉熵代價函數,計算字元預測錯誤率。logprob屬性,刻畫模型對數空間正確下一字母分配概率。變換到對數空間取均值負交叉熵。結果返回線性空間,得到混淆度(perplexity)。混淆度表示模型在每個時間步猜測選項數目。完美模型,混淆度1。每個類別輸出相同概率模型,混淆度為n。如果下一字母零概率,混淆度會變無窮大。預測概率箝位在很小正數和1之間。
固定長度序列,結果tf.reduce_mean。變長序列,與掩碼相乘,屏蔽填充幀,沿幀尺寸聚合,每幀只有一個元素集,tf.reduce_sum聚合各幀為一個標量。
序列實際長度取平均每個序列各幀。使用每個序列長度最大值和1,避免空序列除數為0。tf.reduce_mean取平均批數據樣本。
調用Training(get_params())()。20 epoch 1 小時。20 epochs*200 batches*100 examples*50 characters = 20M個字母。模型在混淆度1.5/字母時收斂。每個字母只需1.5位,可實現文本壓縮。單詞級語言模型,依據單詞數取平均。乘以每個單詞平均字元數。
利用訓練好模型生成新的相似序列。從磁碟載入最新模型檢查點,定義佔位符,數據輸入數據流圖,生成新數據。
構造方法,創建預處理類實例,轉化當前生成序列為NumPy向量,輸入數據流圖。佔位符sequencec預留每批數據一個序列空間。序列長度為2。模型將除最後字元外所有字元作為輸入,除首字元外所有字元作為目標。當前文本最後字元和序列任意第二字元輸入模型。網路為第一字元預測結果,第二字元作目標值。獲取循環神經網路最後活性值,初始化網路下次運行時狀態。模型初始狀態參數,使用過的GRUCell狀態,尺寸rnn_layers*rnn_units向量。
__call__函數,採樣文本序列邏輯。從一個採樣種子開始,每次預測一個字元,當前文本送入網路。相同預處理類轉換當前文本為填充NumPy塊送入網路。批數據只有一個序列和一個輸出幀,只關心索引[0, 0]預測結果。
_sample函數對softmaxl輸出採樣。選取序列最優預測,作為下一幀傳入網路生成序列。實際不是只選擇最可能下一幀,從RNN輸出概率分布隨機採樣。高輸出概率高單詞更可能選中,輸出概率低單詞也可能被選中。
引入溫度參數T,使softmax層輸出分布預測更相似或更不同。在線性空間縮放輸出,變換至指數空間並再次歸一化。運用自然對數撤銷。每個值除以選擇溫度值,得新應用softmax函數。
調用Sampling(get_params())( We , 500) 。捕捉數據內部統計依賴性。
importrequests
importos
frombs4importBeautifulSoup
fromhelpersimportensure_directory
classArxivAbstracts:
ENDPOINT = http://export.arxiv.org/api/query
PAGE_SIZE =100
def__init__(self, cache_dir, categories, keywords, amount=None):
self.categories = categories
self.keywords = keywords
cache_dir = os.path.expanduser(cache_dir)
ensure_directory(cache_dir)
filename = os.path.join(cache_dir, abstracts.txt )
if notos.path.isfile(filename):
withopen(filename, w )asfile_:
forabstractinself._fetch_all(amount):
file_.write(abstract +
)
withopen(filename)asfile_:
self.data = file_.readlines()
def_fetch_all(self, amount):
page_size =type(self).PAGE_SIZE
count =self._fetch_count()
ifamount:
count =min(count, amount)
foroffsetinrange(, count, page_size):
print( Fetch papers {}/{} .format(offset + page_size, count))
yield fromself._fetch_page(page_size, count)
def_fetch_page(self, amount, offset):
url =self._build_url(amount, offset)
response = requests.get(url)
soup = BeautifulSoup(response.text)
forentryinsoup.findAll( entry ):
text = entry.find( summary ).text
text = text.strip().replace(
, )
yieldtext
def_fetch_count(self):
url =self._build_url(,)
response = requests.get(url)
soup = BeautifulSoup(response.text, lxml )
count =int(soup.find( opensearch:totalresults ).string)
print(count, papers found )
returncount
def_build_url(self, amount, offset):
categories = OR .join( cat: + xforxinself.categories)
keywords = OR .join( all: + xforxinself.keywords)
url =type(self).ENDPOINT
url += ?search_query=(({}) AND ({})) .format(categories, keywords)
url += &max_results={}&offset={} .format(amount, offset)
returnurl
importrandom
importnumpyasnp
classPreprocessing:
VOCABULARY =
" $% ()+,-./0123456789:;=?ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"\^_abcdefghijklmnopqrstuvwxyz{}"
def__init__(self, texts, length, batch_size):
self.texts = texts
self.length = length
self.batch_size = batch_size
self.lookup =
def__call__(self, texts):
batch = np.zeros((len(texts),self.length,len(self.VOCABULARY)))
forindex, textinenumerate(texts):
text = [xforxintextifxinself.lookup]
assert2
foroffset, characterinenumerate(text):
code =self.lookup[character]
batch[index, offset, code] =1
returnbatch
def__iter__(self):
windows = []
fortextinself.texts:
foriinrange(,len(text) -self.length +1,self.length //2):
windows.append(text[i: i +self.length])
assertall(len(x) ==len(windows[])forxinwindows)
while True:
random.shuffle(windows)
foriinrange(,len(windows),self.batch_size):
batch = windows[i: i +self.batch_size]
yieldself(batch)
importtensorflowastf
fromhelpersimportlazy_property
classPredictiveCodingModel:
def__init__(self, params, sequence, initial=None):
self.params = params
self.sequence = sequence
self.initial = initial
self.prediction
self.state
self.cost
self.error
self.logprob
self.optimize
@lazy_property
defdata(self):
max_length =int(self.sequence.get_shape()[1])
returntf.slice(self.sequence, (,,), (-1, max_length -1, -1))
@lazy_property
deftarget(self):
returntf.slice(self.sequence, (,1,), (-1, -1, -1))
@lazy_property
defmask(self):
returntf.reduce_max(tf.abs(self.target),reduction_indices=2)
@lazy_property
deflength(self):
returntf.reduce_sum(self.mask,reduction_indices=1)
@lazy_property
defprediction(self):
prediction, _ =self.forward
returnprediction
@lazy_property
defstate(self):
_, state =self.forward
returnstate
@lazy_property
defforward(self):
cell =self.params.rnn_cell(self.params.rnn_hidden)
cell = tf.nn.rnn_cell.MultiRNNCell([cell] *self.params.rnn_layers)
hidden, state = tf.nn.dynamic_rnn(
inputs=self.data,
cell=cell,
dtype=tf.float32,
initial_state=self.initial,
sequence_length=self.length)
vocabulary_size =int(self.target.get_shape()[2])
prediction =self._shared_softmax(hidden, vocabulary_size)
returnprediction, state
@lazy_property
defcost(self):
prediction = tf.clip_by_value(self.prediction,1e-10,1.0)
cost =self.target * tf.log(prediction)
cost = -tf.reduce_sum(cost,reduction_indices=2)
returnself._average(cost)
@lazy_property
deferror(self):
error = tf.not_equal(
tf.argmax(self.prediction,2), tf.argmax(self.target,2))
error = tf.cast(error, tf.float32)
returnself._average(error)
@lazy_property
deflogprob(self):
logprob = tf.mul(self.prediction,self.target)
logprob = tf.reduce_max(logprob,reduction_indices=2)
logprob = tf.log(tf.clip_by_value(logprob,1e-10,1.0)) / tf.log(2.0)
returnself._average(logprob)
@lazy_property
defoptimize(self):
gradient =self.params.optimizer.compute_gradients(self.cost)
ifself.params.gradient_clipping:
limit =self.params.gradient_clipping
gradient = [
(tf.clip_by_value(g, -limit, limit), v)
ifgis not None else(None, v)
forg, vingradient]
optimize =self.params.optimizer.apply_gradients(gradient)
returnoptimize
def_average(self, data):
data *=self.mask
length = tf.reduce_sum(self.length,)
data = tf.reduce_sum(data,reduction_indices=1) / length
data = tf.reduce_mean(data)
returndata
def_shared_softmax(self, data, out_size):
max_length =int(data.get_shape()[1])
in_size =int(data.get_shape()[2])
weight = tf.Variable(tf.truncated_normal(
[in_size, out_size],stddev=0.01))
bias = tf.Variable(tf.constant(0.1,shape=[out_size]))
# Flatten to apply same weights to all time steps.
flat = tf.reshape(data, [-1, in_size])
output = tf.nn.softmax(tf.matmul(flat, weight) + bias)
output = tf.reshape(output, [-1, max_length, out_size])
returnoutput
importos
importre
importtensorflowastf
importnumpyasnp
fromhelpersimportoverwrite_graph
fromhelpersimportensure_directory
fromArxivAbstractsimportArxivAbstracts
fromPreprocessingimportPreprocessing
fromPredictiveCodingModelimportPredictiveCodingModel
classTraining:
@overwrite_graph
def__init__(self, params, cache_dir, categories, keywords, amount=None):
self.params = params
self.texts = ArxivAbstracts(cache_dir, categories, keywords, amount).data
self.prep = Preprocessing(
self.texts,self.params.max_length,self.params.batch_size)
self.sequence = tf.placeholder(
tf.float32,
[None,self.params.max_length,len(self.prep.VOCABULARY)])
self.model = PredictiveCodingModel(self.params,self.sequence)
self._init_or_load_session()
def__call__(self):
print( Start training )
self.logprobs = []
batches =iter(self.prep)
forepochinrange(self.epoch,self.params.epochs +1):
self.epoch = epoch
for_inrange(self.params.epoch_size):
self._optimization(next(batches))
self._evaluation()
returnnp.array(self.logprobs)
def_optimization(self, batch):
logprob, _ =self.sess.run(
(self.model.logprob,self.model.optimize),
{self.sequence: batch})
ifnp.isnan(logprob):
raiseException( training diverged )
self.logprobs.append(logprob)
def_evaluation(self):
self.saver.save(self.sess, os.path.join(
self.params.checkpoint_dir, model ),self.epoch)
self.saver.save(self.sess, os.path.join(
self.params.checkpoint_dir, model ),self.epoch)
perplexity =2** -(sum(self.logprobs[-self.params.epoch_size:]) /
self.params.epoch_size)
print( Epoch {:2d} perplexity {:5.4f} .format(self.epoch, perplexity))
def_init_or_load_session(self):
self.sess = tf.Session()
self.saver = tf.train.Saver()
checkpoint = tf.train.get_checkpoint_state(self.params.checkpoint_dir)
ifcheckpointandcheckpoint.model_checkpoint_path:
path = checkpoint.model_checkpoint_path
print( Load checkpoint , path)
self.saver.restore(self.sess, path)
self.epoch =int(re.search(r -(d+)$ , path).group(1)) +1
else:
ensure_directory(self.params.checkpoint_dir)
print( Randomly initialize variables )
self.sess.run(tf.initialize_all_variables())
self.epoch =1
fromTrainingimportTraining
fromget_paramsimportget_params
Training(
get_params(),
cache_dir= ./arxiv ,
categories= [
Machine Learning ,
Neural and Evolutionary Computing ,
Optimization
],
keywords= [
neural ,
network ,
deep
]
)()
importtensorflowastf
importnumpyasnp
fromhelpersimportoverwrite_graph
fromPreprocessingimportPreprocessing
fromPredictiveCodingModelimportPredictiveCodingModel
classSampling:
@overwrite_graph
def__init__(self, params):
self.params = params
self.prep = Preprocessing([],2,self.params.batch_size)
self.sequence = tf.placeholder(
tf.float32, [1,2,len(self.prep.VOCABULARY)])
self.state = tf.placeholder(
tf.float32, [1,self.params.rnn_hidden *self.params.rnn_layers])
self.model = PredictiveCodingModel(
self.params,self.sequence,self.state)
self.sess = tf.Session()
checkpoint = tf.train.get_checkpoint_state(self.params.checkpoint_dir)
ifcheckpointandcheckpoint.model_checkpoint_path:
tf.train.Saver().restore(
self.sess, checkpoint.model_checkpoint_path)
else:
print( Sampling from untrained model. )
print( Sampling temperature ,self.params.sampling_temperature)
def__call__(self, seed, length=100):
text = seed
state = np.zeros((1,self.params.rnn_hidden *self.params.rnn_layers))
for_inrange(length):
feed = {self.state: state}
feed[self.sequence] =self.prep([text[-1] + ? ])
prediction, state =self.sess.run(
[self.model.prediction,self.model.state], feed)
text +=self._sample(prediction[,])
returntext
def_sample(self, dist):
dist = np.log(dist) /self.params.sampling_temperature
dist = np.exp(dist) / np.exp(dist).sum()
choice = np.random.choice(len(dist),p=dist)
choice =self.prep.VOCABULARY[choice]
returnchoice
參考資料:
《面向機器智能的TensorFlow實踐》
TAG:清醒瘋子 |
※iPhone 2019新賣點預測:WiFi 6、改進Face ID、三攝像頭
※2019 年科技產業大預測:Micro LED、5G、語音識別都上榜
※Yann LeCun、吳恩達等的2019年AI趨勢預測
※從 iOS 11.3到iOS 12:iPhone 系統更新預測
※蘋果WWDC 2018預測:Siri終於要更新、FaceTime支持群聊
※Wikibon:2018大數據和機器學習的預測
※蘋果新機預測:發布6.1寸版iPhone和6.5寸版iPhone X Plus
※I/O 2018大會下周見,大膽預測 Material Design 2.0 設計語言
※KGI發布蘋果新iPhone價格預測:iPhone X Plus預計1099刀
※Stock Watch的預測《賽博朋克2077》將成為史上銷售最快的RPG
※Doyle預測:全球SD-WAN服務將達100億美元
※12.4 VR掃描:英偉達發布2499美元GPU;CCS Insight預測2018年VR/AR頭顯銷量800萬台
※Gartner:2019數據和分析技術十大趨勢預測
※郭明錤預測2019 iPhone天線軟板材質大改:捨棄LCP材料改採用MPI
※基於突變特徵的BRCA1/2缺陷預測模型-HRDetect
※大膽預測:2018款iPhone X Plus將支持Apple Pencil
※郭銘琪預測:2018 iPad Pro將具備USB-C介面,新版Macbook支持Touch ID指紋認證
※SuperData報告預測2019年Oculus Quest銷量將超過100萬台
※Yann LeCun、吳恩達等多位專家的2019年AI發展預測
※MarketsandMarkets預測:2023年AR市場規模將超600億美元