用 TensorFlow 可以做什麼有意思的事情?


不知道怎麼樣的題主認為才算有意思。

===============================

我認為有意思的:

圖像處理方面:

  • 圖像風格轉換,neural-style可以生成各種有意思的圖: anishathalye/neural-style

  • 給素描黑白畫,自動上色:pfnet/PaintsChainer

  • 圖像描述,image caption:im2txt

人臉方面:

  • 微軟給出的猜年齡的應用 How old do I look?

  • 之前小度機器人的跨年齡識別,基於你現在的照片,識別出小時候的你

  • GAN生成格式各樣的人臉 GANs-生成對抗網路 (生成明星臉)
  • 人臉顏值自動打分
  • 判斷女明星是否整容

nlprnn

  • 生成古詩詞:基於RNN生成古詩詞
  • 創作歌曲,歌曲風格轉換

Reinforcement learning

  • 結合RL玩遊戲的,憤怒的小鳥,超級馬里奧 DeepLearningFlappyBird

  • 還有模擬自動駕駛的,用TensorFlow實現MarioKart遊戲自動駕駛(TensorKart),Udacity自駕模擬項目Nanodegree(upul/behavioral_cloning)

===============================

我覺得現在學習deep learning,猶如學習功夫一樣,內外兼修,數學建模能力,網路結構建模等能力是內功,在各個領域的應用是招式,現在各式各樣的招式都有。

總之,能做到非常多的好玩有意思的東西


可以用TensorFlow來搞定「倒字驗證碼」。

——————

前段時間心血來潮,想寫幾個爬蟲,但是實操過的同學都知道,現在爬蟲程序對很多網站都無效。

仔細一想,其實是驗證碼問題,12306的坑爹驗證碼先不說,現在很多站都流行用「倒字驗證碼」:

需要在一排漢字中找到,簡單看了下,大概7個漢字,不定數個漢字是倒置的,需要人為指出哪些漢字是倒置的,和以往常規的驗證碼識別有點區別,有點意思!!!

今天就給大家分享一下,如何用TensorFlow搞定「倒字驗證碼」,問題很明確,主要是那個:

  • 數據問題?如何生成這些數據
  • 切字+單個分類器,還是直接輸出所有的倒置情況(保證驗證碼字數一致)

數據準備

有天沙神在群里發了個鏈接,python生成漢字的代碼, 正好用得上,改改然後很快就搞定了,代碼如下:

# -*- coding: utf-8 -*-
from PIL import Image,ImageDraw,ImageFont
import random
import math, string
import logging
# logger = logging.Logger(name="gen verification")

class RandomChar():
@staticmethod
def Unicode():
val = random.randint(0x4E00, 0x9FBF)
return unichr(val)

@staticmethod
def GB2312():
head = random.randint(0xB0, 0xCF)
body = random.randint(0xA, 0xF)
tail = random.randint(0, 0xF)
val = ( head &<&< 8 ) | (body &<&< 4) | tail str = "%x" % val return str.decode("hex").decode("gb2312") class ImageChar(): def __init__(self, fontColor = (0, 0, 0), size = (100, 40), fontPath = "/Library/Fonts/Arial Unicode.ttf", bgColor = (255, 255, 255), fontSize = 20): self.size = size self.fontPath = fontPath self.bgColor = bgColor self.fontSize = fontSize self.fontColor = fontColor self.font = ImageFont.truetype(self.fontPath, self.fontSize) self.image = Image.new("RGB", size, bgColor) def drawText(self, pos, txt, fill): draw = ImageDraw.Draw(self.image) draw.text(pos, txt, font=self.font, fill=fill) del draw def drawTextV2(self, pos, txt, fill, angle=180): image=Image.new("RGB", (25,25), (255,255,255)) draw = ImageDraw.Draw(image) draw.text( (0, -3), txt, font=self.font, fill=fill) w=image.rotate(angle, expand=1) self.image.paste(w, box=pos) del draw def randRGB(self): return (0,0,0) def randChinese(self, num, num_flip): gap = 1 start = 0 num_flip_list = random.sample(range(num), num_flip) # logger.info("num flip list:{0}".format(num_flip_list)) print "num flip list:{0}".format(num_flip_list) char_list = [] for i in range(0, num): char = RandomChar().GB2312() char_list.append(char) x = start + self.fontSize * i + gap + gap * i if i in num_flip_list: self.drawTextV2((x, 6), char, self.randRGB()) else: self.drawText((x, 0), char, self.randRGB()) return char_list, num_flip_list def save(self, path): self.image.save(path) err_num = 0 for i in range(10): try: ic = ImageChar(fontColor=(100,211, 90), size=(280,28), fontSize = 25) num_flip = random.randint(3,6) char_list, num_flip_list = ic.randChinese(10, num_flip) ic.save("".join(char_list)+"_"+"".join(str(i) for i in num_flip_list)+".jpeg") except: err_num += 1 continue

為了簡單,沒有在生成的字加一些雜訊,顏色什麼的干擾的東西, 生成的圖像差不多這樣

所以,接下來就是在tensorflow構建網路來識別了

模型

網路設計

受項亮的end2end定長的OCR識別的啟發, 因為我這裡的驗證碼都是長度為10的,所以我們只需要構造網路,最後的output有10個輸出,每個輸出為1個二類分類器:

其中,0表示正常,1表示倒置,這樣就可以構造一個input到10個binary classification的網路,網路結構很簡單(小夥伴們可以在這裡都試試網路的設計,多試試黑科技),好吧,廢話不多說,show you code:

def network():
images = tf.placeholder(dtype=tf.float32, shape=[None, 28, 280, 1], name="image_batch")
labels = tf.placeholder(dtype=tf.int32, shape=[None, 10], name="label_batch")
endpoints = {}
conv_1 = slim.conv2d(images, 32, [5,5],1, padding="SAME")
avg_pool_1 = slim.avg_pool2d(conv_1, [2,2],[1,1], padding="SAME")
conv_2 = slim.conv2d(avg_pool_1, 32, [5,5], 1,padding="SAME")
avg_pool_2 = slim.avg_pool2d(conv_2, [2,2],[1,1], padding="SAME")
conv_3 = slim.conv2d(avg_pool_2, 32, [3,3])
avg_pool_3 = slim.avg_pool2d(conv_3, [2,2], [1,1])
flatten = slim.flatten(avg_pool_3)
fc1 = slim.fully_connected(flatten, 512, activation_fn=None)
out0 = slim.fully_connected(fc1,2, activation_fn=None)
out1 = slim.fully_connected(fc1,2, activation_fn=None)
out2 = slim.fully_connected(fc1,2, activation_fn=None)
out3 = slim.fully_connected(fc1,2, activation_fn=None)
out4 = slim.fully_connected(fc1,2, activation_fn=None)
out5 = slim.fully_connected(fc1,2, activation_fn=None)
out6 = slim.fully_connected(fc1,2, activation_fn=None)
out7 = slim.fully_connected(fc1,2, activation_fn=None)
out8 = slim.fully_connected(fc1,2, activation_fn=None)
out9 = slim.fully_connected(fc1,2, activation_fn=None)
global_step = tf.Variable(initial_value=0)
out0_argmax = tf.expand_dims(tf.argmax(out0, 1), 1)
out1_argmax = tf.expand_dims(tf.argmax(out1, 1), 1)
out2_argmax = tf.expand_dims(tf.argmax(out2, 1), 1)
out3_argmax = tf.expand_dims(tf.argmax(out3, 1), 1)
out4_argmax = tf.expand_dims(tf.argmax(out4, 1), 1)
out5_argmax = tf.expand_dims(tf.argmax(out5, 1), 1)
out6_argmax = tf.expand_dims(tf.argmax(out6, 1), 1)
out7_argmax = tf.expand_dims(tf.argmax(out7, 1), 1)
out8_argmax = tf.expand_dims(tf.argmax(out8, 1), 1)
out9_argmax = tf.expand_dims(tf.argmax(out9, 1), 1)
out_score = tf.concat([out0, out1, out2, out3, out4, out5, out6, out7, out8, out9], axis=1)
out_final = tf.cast(tf.concat([out0_argmax, out1_argmax, out2_argmax, out3_argmax, out4_argmax, out5_argmax, out6_argmax, out7_argmax, out8_argmax, out9_argmax], axis=1), tf.int32)

loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=out0, labels=tf.one_hot(labels[:,0],depth=2)))
loss1 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=out1, labels=tf.one_hot(labels[:,1],depth=2)))
loss2 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=out2, labels=tf.one_hot(labels[:,2],depth=2)))
loss3 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=out3, labels=tf.one_hot(labels[:,3],depth=2)))
loss4 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=out4, labels=tf.one_hot(labels[:,4],depth=2)))
loss5 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=out5, labels=tf.one_hot(labels[:,5],depth=2)))
loss6 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=out6, labels=tf.one_hot(labels[:,6],depth=2)))
loss7 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=out7, labels=tf.one_hot(labels[:,7],depth=2)))
loss8 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=out8, labels=tf.one_hot(labels[:,8],depth=2)))
loss9 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=out9, labels=tf.one_hot(labels[:,9],depth=2)))
loss_list= [loss, loss1, loss2, loss3,loss4, loss5, loss6, loss7, loss8, loss9]
loss_sum = tf.reduce_sum(loss_list)
train_op = tf.train.AdamOptimizer(learning_rate=0.0001).minimize(loss_sum, global_step=global_step)
accuracy = tf.reduce_mean(tf.cast(tf.reduce_all(tf.equal(out_final, labels), axis=1), tf.float32))
tf.summary.scalar("loss_sum", loss_sum)
tf.summary.scalar("accuracy", accuracy)
merged_summary_op = tf.summary.merge_all()

endpoints["global_step"] = global_step
endpoints["images"] = images
endpoints["labels"] = labels
endpoints["train_op"] = train_op
endpoints["loss_sum"] = loss_sum
endpoints["accuracy"] = accuracy
endpoints["merged_summary_op"] = merged_summary_op
endpoints["out_final"] = out_final
endpoints["out_score"] = out_score
return endpoints

注意tf1.0和tf0.n裡面有一些api介面改了,這裡的代碼是tf1.0的要改成0.n大概需要改下tf.concat,另外因為label是10為binary的數,所以這裡很顯然,loss續傳重新設計,這裡把10為的loss全加起來作為去優化的object func

其實我覺得這裡可以用更多的方法,因為這裡的label可以看出一個10位上的數據分布,因為我們的predict和原先的groundtruth的分布的差異,比如kl距離都可以嘗試,我這裡簡單粗暴的直接加起來了,另外就是tf.reduce_all的使用

意思是只要其中有任意為false,則結果為false,恰好滿足我這裡必須10位都相同才視為識別正確

其他的代碼沒什麼特別好說明的,想要學習這些api的直接run下代碼就好了,再有不懂的直接在我文章下面留言,我會第一時間回復

模型訓練

def train():
train_feeder = DataIterator(data_dir=FLAGS.train_data_dir)
test_feeder = DataIterator(data_dir=FLAGS.test_data_dir)
with tf.Session() as sess:
train_images, train_labels = train_feeder.input_pipeline(batch_size=FLAGS.batch_size, aug=True)
test_images, test_labels = test_feeder.input_pipeline(batch_size=FLAGS.batch_size)
endpoints = network()
sess.run(tf.global_variables_initializer())
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
saver = tf.train.Saver()

train_writer = tf.summary.FileWriter("./log" + "/train",sess.graph)
test_writer = tf.summary.FileWriter("./log" + "/val")
start_step = 0
if FLAGS.restore:
ckpt = tf.train.latest_checkpoint(FLAGS.checkpoint_dir)
if ckpt:
saver.restore(sess, ckpt)
print "restore from the checkpoint {0}".format(ckpt)
start_step += int(ckpt.split("-")[-1])
logger.info(":::Training Start:::")
try:
while not coord.should_stop():
start_time = time.time()
train_images_batch, train_labels_batch = sess.run([train_images, train_labels])
feed_dict = {endpoints["images"]: train_images_batch, endpoints["labels"]: train_labels_batch}
_, loss_val, train_summary, step = sess.run([endpoints["train_op"], endpoints["loss_sum"], endpoints["merged_summary_op"], endpoints["global_step"]], feed_dict=feed_dict)
train_writer.add_summary(train_summary, step)
end_time = time.time()
logger.info("[train] the step {0} takes {1} loss {2}".format(step, end_time-start_time, loss_val))
if step &> FLAGS.max_steps:
break
if step % FLAGS.eval_steps == 1:
logger.info("========Begin eval stage =========")
start_time = time.time()
# can"t run
test_images_batch, test_labels_batch = sess.run([test_images, test_labels])
logger.info("[test] gen test batch spend {0}".format(time.time()-start_time))
feed_dict = {
endpoints["images"]: test_images_batch,
endpoints["labels"]: test_labels_batch
}
accuracy_val,test_summary = sess.run([endpoints["accuracy"], endpoints["merged_summary_op"]], feed_dict=feed_dict)
end_time = time.time()
test_writer.add_summary(test_summary, step)
logger.info( "[test] the step {0} accuracy {1} spend time {2}".format(step, accuracy_val, (end_time-start_time)))
if step % FLAGS.save_steps == 1:
logger.info("Save the ckpt of {0}".format(step))
saver.save(sess, os.path.join(FLAGS.checkpoint_dir, "my-model"), global_step=endpoints["global_step"])
except tf.errors.OutOfRangeError:
# print "============train finished========="
logger.info("==================Train Finished================")
saver.save(sess, os.path.join(FLAGS.checkpoint_dir, "my-model"), global_step=endpoints["global_step"])
finally:
coord.request_stop()
coord.join(threads)

訓練過程會新建兩個DataIterator的對象,這樣就可以在訓練的過程中對test的dataset來做訓練的驗證,訓練過程的loss和accuracy見下圖:

大家可以看看大概到了4000多個step的時候,train和val的batch就的accuracy就特別高了,可能是我這裡的train和val的dataset都太simple的,所以模型的訓練很快就可以達到很高的性能,為了測試這裡的模型是不是扯淡,

照常寫了validation來做所有test dataset的數據集上accuracy的驗證

模型驗證

def validation():
# it should be fixed by using placeholder with epoch num in train stage
logger.info("=======Validation Beigin=======")
test_feeder = DataIterator(data_dir="../data/test_data/")
predict_labels_list = []
groundtruth = []
with tf.Session() as sess:
test_images, test_labels = test_feeder.input_pipeline(batch_size=FLAGS.batch_size,num_epochs=1)
endpoints = network()
sess.run(tf.global_variables_initializer())
sess.run(tf.local_variables_initializer())
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
saver = tf.train.Saver()
ckpt = tf.train.latest_checkpoint(FLAGS.checkpoint_dir)
if ckpt:
saver.restore(sess, ckpt)
logger.info("restore from the checkpoint {0}".format(ckpt))
logger.info("======Start Validation=======")
try:
i = 0
acc_sum = 0.0
while not coord.should_stop():
i += 1
start_time = time.time()
test_images_batch, test_labels_batch = sess.run([test_images, test_labels])
feed_dict = {endpoints["images"]:test_images_batch, endpoints["labels"]: test_labels_batch}
labels_batch, predict_labels_batch, acc = sess.run([endpoints["labels"],endpoints["out_final"], endpoints["accuracy"]], feed_dict=feed_dict)
predict_labels_list += predict_labels_batch.tolist()
groundtruth += labels_batch.tolist()
acc_sum += acc
logger.info("the batch {0} takes {1} seconds, accuracy {2}".format(i, time.time()-start_time, acc))
except tf.errors.OutOfRangeError:
logger.info("==================Validation Finished===================")
logger.info("The finally accuracy {0}".format(acc_sum/i))
finally:
coord.request_stop()
coord.join(threads)
return {"predictions":predict_labels_list, "gt_labels":groundtruth}

因為我這邊太暴力了,在生成數據集的時候,訓練數據100w(有生成異常,最終80多萬張),測試數據60w(最後好像有40多w成功生成的), 跑一次全測試數據集也好長時間,但是看了好久的輸出,都是下面的結果,嚇死我了,全是1:

模型inference

有點害怕是不是代碼寫錯的原因,再次確認,寫了個inference:

def inference(image):
logger.info("============inference==========")
temp_image = Image.open(image).convert("L")
# temp_image = temp_image.resize((FLAGS.image_height, FLAGS.image_size),Image.ANTIALIAS)
temp_image = np.asarray(temp_image) / 255.0
temp_image = temp_image.reshape([-1, 28, 280, 1])
sess = tf.Session()
logger.info("========start inference============")
# images = tf.placeholder(dtype=tf.float32, shape=[None, 280, 28, 1])
endpoints = network()
saver = tf.train.Saver()
ckpt = tf.train.latest_checkpoint(FLAGS.checkpoint_dir)
if ckpt:
saver.restore(sess, ckpt)
feed_dict = {endpoints["images"]: temp_image}
predict_val, predict_index = sess.run([endpoints["out_score"],endpoints["out_final"]], feed_dict=feed_dict)
sess.close()
return predict_val, predict_index

隨機找了張圖像,然後做了下inference,結果是

這裡稍微做下解釋../data/test_data/092e9ae8-ee91-11e6-91c1-525400551618_69128.jpeg文件名前面有uuid+』_』+』label』組成,最開始我是把uuid部分用漢字表示,這樣生成的圖像既有漢字信息又有label信息,

在我本地mac上是ok的可以生成的,但是在ubuntu的雲主機上,可能是漢字的不支持的原因,寫入文件為漢字的時候,就生成不了,太忙了暫時沒有解決這個問題。這裡的label 69128轉換為10位binary 就是0110001011,看看我的結果

所以好像是沒有大的問題。

總結

照例做個總結,綜上,這次主要是設計一個小的網路做一個單input,多output的網路,然後確定一個loss作為目標函數來最小化,整個網路很簡單,但是確實是很有效,另外因為數據還有字數都是自己DIY的,當然不能直接使用,但是選擇好合適字體,做一些扭曲變換,應該會很快cover到真正的生產環境上來,對此很有信心。

有興趣的小伙幫可以fork下項目,然後探索下把倒字驗證碼搞定,以上的東西純屬拋磚引玉,有興趣的小夥伴一起玩呀。

所有的代碼都在tensorflow-101/zhihu_code,感覺有意思的star下吧,我們一起來玩。

——————

相關閱讀推薦:

機器學習進階筆記之八 | TensorFlow與中文手寫漢字識別

機器學習進階筆記之七 | MXnet初體驗

機器學習進階筆記之六 | 深入理解Fast Neural Style

機器學習進階筆記之五 | 深入理解VGGResidual Network

機器學習進階筆記之四 | 深入理解GoogLeNet

機器學習進階筆記之三 | 深入理解Alexnet

機器學習進階筆記之二 | 深入理解Neural Style

機器學習進階筆記之一 | TensorFlow安裝與入門

關於作者:

Burness(@想飛的石頭), UCloud平台研發中心深度學習研發工程師,tflearn Contributor tensorflow Contributor,做過電商推薦、精準化營銷相關演算法工作,專註於分散式深度學習框架、計算機視覺演算法研究,平時喜歡玩玩演算法,研究研究開源的項目,偶爾也會去一些數據比賽打打醬油,生活中是個極客,對新技術、新技能痴迷。

你可以在Github上找到他:http://hacker.duanshishi.com/

「UCloud機構號」將獨家分享雲計算領域的技術洞見、行業資訊以及一切你想知道的相關訊息。歡迎提問求關注 o(*////▽////*)q~

現在註冊使用UCloud,還有首充返現優惠,最高可返3000元代金券!活動傳送門:用UCloud!3000元限量版禮盒等你來拆!

另,歡迎添加UCloud運營小妹個人微信號:Surdur,陪聊很專業:)

以上。


用TensorFlow構建自己的神經機器翻譯系統是不是有意思的事情?

前短時間,谷歌官方在 Github 開放了一份神經機器翻譯教程,該教程從基本概念實現開始,首先搭建了一個簡單的NMT模型,隨後更進一步引進注意力機制和多層 LSTM 加強系統的性能,最後谷歌根據 GNMT 提供了更進一步改進的技巧和細節,這些技巧能令該NMT系統達到極其高的精度。

機器之心對該教程進行了簡要的描述,如下文。(詳細和精確的內容請查看項目原網站)

機器翻譯,即跨語言間的自動翻譯,是機器學習社區最活躍的研究領域。在機器翻譯的眾多方法中,序列到序列(sequence-to-sequence,seq2seq)模型 [1, 2] 近期獲得巨大成功。由於其可以使用深度神經網路獲取句義,該模型成為谷歌翻譯等多數商業翻譯系統事實上的標準模型。但是,儘管有關 OpenNMT 或 tf-seq2seq 等 seq2seq 模型的資料已經非常豐富,但能夠指導人們快速構建高質量翻譯系統的知識和技能仍然略顯不足。

今天,我們很高興能夠發布最新的 TensorFlow 神經機器翻譯教程,幫助讀者全面了解 seq2seq 模型,並介紹如何從頭開始構建有競爭力的翻譯模型。該教程儘可能簡單地呈現該過程,教程首先介紹神經機器翻譯的背景知識,並講述構建 vanilla 系統的具體代碼。然後介紹注意力機制 [3, 4] 這一幫助 NMT 系統處理長句的重要工具。最後,本教程將講解如何複製谷歌 NMT(GNMT)系統 [5] 的關鍵特徵,以實現在多個 GPU 上訓練模型。

本教程包括具體的基準測試結果,用戶可自行複製。我們的模型提供強大的開源基準,其性能不亞於 GNMT 的結果 [5]。我們在 WMT 2014 的英語轉德語翻譯任務中取得了 BLEU 得分 24.4 的成績。

本教程還包括其他的基準測試結果(英語轉越南語、德語轉英語)。

另外,本教程將開放全動態的 seq2seq API(隨 TensorFlow 1.2 發布),該 API 使 seq2seq 模型的構建過程乾淨、簡單、易讀:

  • 使用 tf.contrib.data 中最新輸入的管道對動態調整的輸入序列進行預處理。
  • 使用批量填充和序列長度 bucketing,提高訓練速度和推理速度。
  • 使用通用結構和訓練時間表訓練 seq2seq 模型,包括多種注意力機制和固定抽樣。
  • 使用 in-graph 集束搜索在 seq2seq 模型中進行推理。
  • 優化 seq2seq 模型,以實現在多 GPU 設置中的模型訓練。

下文我們將簡要地介紹該 Github 教程項目。

引言

序列到序列(seq2seq)模型(Sutskever et al., 2014, Cho et al., 2014)在機器翻譯、語音識別和文本摘要等任務上取得了巨大的成功。本教程致力於幫助讀者全面掌握 seq2seq 模型,並且展示了如何從頭開始構建一個強大的 seq2seq 模型。我們該教程會注重神經機器翻譯(NMT)任務,神經機器翻譯是 seq2seq 模型很好的試驗台,並且已經獲得了廣泛的成功。我們使用的代碼是極其輕量、高質量、可投入生產並且結合了最新研究思路的實現。我們通過以下方式實現這一目標:

  1. 使用最新的解碼器/attention wrapper API、TensorFlow 1.2 數據迭代器。
  2. 結合了我們在構建循環型和 seq2seq 型模型的專業知識。
  3. 提供了可構建最好 NMT 模型的技巧,同時還複製了谷歌的 NMT(GNMT)系統。

我們相信提供所有人都很容易複製的基準是非常重要的。因此,我們基於以下公開的數據集提供了全部的試驗結果和預訓練模型:

  1. 小規模數據集:TED 演講的英語-越南語平行語料庫(133K 個句子對),該數據集由 IWSLT Evaluation Campaign 提供。
  2. 大規模數據集:德語-英語平行語料庫(4.5M 個句子對),該數據集由 WMT Evaluation Campaign 提供。

我們首先需要了解用於 NMT 任務的 seq2seq 模型的基本知識,並需要理解如何構建和訓練一個 vanilla NMT 模型。第二部分將更進一步詳細地解釋如何構建帶注意力機制的強大神經機器翻譯模型。然後我們會討論構建更好神經機器翻譯模型(翻譯速度和質量)可能的技巧,例如 TensorFlow 最好的實踐方法(batching, bucketing)、雙向循環神經網路和集束搜索等。

基礎

關於神經機器翻譯

以片語為基礎的傳統翻譯系統將源語言句子拆分成多個詞塊,然後進行詞對詞的翻譯。這使得翻譯輸出結果流暢性大打折扣,遠遠不如人類譯文。我們會通讀整個源語言句子、了解句子含義,然後輸出翻譯結果。神經機器翻譯(NMT)竟然可以模仿人類的翻譯過程!

圖 1. 編碼器-解碼器結構——神經機器翻譯的通用方法實例。編碼器將源語言句子轉換成「意義」向量,然後通過解碼器輸出翻譯結果。

具體來說,神經機器翻譯系統首先使用編碼器讀取源語言句子,構建一個「思想」向量,即代表句義的一串數字;然後使用解碼器處理該容器,並輸出翻譯結果,如圖 1 所示。這就是我們通常所說的編碼器-解碼器結構。神經機器翻譯用這種方法解決以片語為基礎的傳統翻譯系統遇到的翻譯問題:神經機器翻譯能夠捕捉語言中的長距離依賴結構,如詞性一致、句法結構等,然後輸出流利度更高的翻譯結果,正如谷歌神經機器翻譯系統已經做到的那樣。

NMT 模型在具體的結構中會發生變化。對於序列數據而言,最好的選擇是循環神經網路(RNN),這也被大多數 NMT 模型採用。通常情況下,編碼器和解碼器都可使用循環神經網路。但是,循環神經網路模型在下列情況下發生變化:(a)方向性(directionality),單向或雙向;(b)深度,單層或多層;(c)類型,通常是 vanilla RNN、長短期記憶(Long Short-term Memory,LSTM),或門控循環單元(gated recurrent unit,GRU)。

感興趣的讀者可打開該網址,獲取 RNN 和 LSTM 的更多信息。

本教程中,我們將以單向的深度多層 RNN(deep multi-layer RNN)為例,它使用 LSTM 作為循環單元。模型實例如圖 2 所示。我們在該實例中構建了一個模型,將源語言句子「I am a student」翻譯成目標語言「Je suis étudiant」。該 NMT 模型包括兩個循環神經網路:編碼器 RNN,在不預測的情況下將輸入的源語言單詞進行編碼;解碼器,在預測下一個單詞的條件下處理目標句子。

若想參考更多信息,請查看Luong(2016)。

圖 2. 神經機器翻譯——一個深度循環結構實例:將源語言句子「I am a student」翻譯成目標語言句子「Je suis étudiant」。此處,「&」代表解碼過程開始,「&」代表解碼過程結束。

安裝該教程

為了安裝該教程,我們需要先安裝 TensorFlow。本教程需要最新的 TensorFlow 教程(目前為 1.2.1 版本)。為了安裝 TensorFlow,請按照以下安裝指導:https://www.tensorflow.org/install/。

在安裝 TensorFlow 之後,我們需要運行以下命令安裝本教程的源代碼:

git clone https://github.com/tensorflow/nmt/

訓練-如何構建我們第一個 NMT 系統

我們首先需要了解構建一個 NMT 模型具體代碼的核心,我們會在圖 2 中更詳細地講解。我們後面會介紹數據準備和全部的代碼,這一部分是指 model.py 文件。

在網路的底層,編碼器和解碼器 RNN 接收到以下輸入:首先是原句子,然後是從編碼到解碼模式的過渡邊界符號「&」,最後是目標語句。對於訓練來說,我們將為系統提供以下張量,它們是以時間為主(time-major)的格式,並包括了單詞索引:

  • encoder_inputs [max_encoder_time, batch_size]:源輸入詞。
  • decoder_inputs [max_decoder_time, batch_size]:目標輸入詞。
  • decoder_outputs [max_decoder_time, batch_size]:目標輸出詞,這些是 decoder_inputs 按一個時間步向左移動,並且在右邊有句子結束符。

為了更高的效率,我們一次用多個句子(batch_size)進行訓練。測試略有不同,我們會在後面討論。

1.嵌入

給定單詞的分類屬性,模型首先必須查找詞來源和目標嵌入以檢索相應的詞表徵。為了令該嵌入層能夠運行,我們首先需要為每一種語言選定一個辭彙表。通常,選定辭彙表大小 V,那麼頻率最高的 V 個詞將視為唯一的。而所有其他的詞將轉換並打上「unknown」標誌,因此所有的詞將有相同的嵌入。我們通常在訓練期間嵌入權重,並且每種語言都有一套。

# Embedding
embedding_encoder = variable_scope.get_variable(
"embedding_encoder", [src_vocab_size, embedding_size], ...)# Look up embedding:# encoder_inputs: [max_time, batch_size]# encoder_emp_inp: [max_time, batch_size, embedding_size]
encoder_emb_inp = embedding_ops.embedding_lookup(
embedding_encoder, encoder_inputs)

我們同樣可以構建 embedding_decoder 和 decoder_emb_inp。注意我們可以選擇預訓練的詞表徵如 word2vec 或 Glove vectors 初始化嵌入權重。通常給定大量的訓練數據,我們能從頭學習這些嵌入權重。

2.編碼器

一旦可以檢索到,詞嵌入就能作為輸入饋送到主神經網路中。該網路有兩個多層循環神經網路組成,一個是原語言的編碼器,另一個是目標語言的解碼器。這兩個 RNN 原則上可以共享相同的權重,然而在實踐中,我們通常使用兩組不同的循環神經網路參數(這些模型在擬合大型訓練數據集上做得更好)。解碼器 RNN 使用零向量作為它的初始狀態,並且可以使用如下代碼構建:

# Build RNN cell
encoder_cell = tf.nn.rnn_cell.BasicLSTMCell(num_units)
# Run Dynamic RNN# encoder_outpus: [max_time, batch_size, num_units]# encoder_state: [batch_size, num_units]
encoder_outputs, encoder_state = tf.nn.dynamic_rnn(
encoder_cell, encoder_emb_inp,
sequence_length=source_seqence_length, time_major=True

注意語句有不同的長度以避免浪費計算力,因此我們會通過 source_seqence_length 告訴 dynamic_rnn 精確的句子長度。因為我們的輸入是以時間為主(time major)的,我們需要設定 time_major=True。現在我們暫時只需要構建單層 LSTM、encoder_cell。我們後面會詳細描述怎樣構建多層 LSTM、添加 dropout 並使用注意力機制。

3.解碼器

decoder 也需要訪問源信息,一種簡單的方式是用編碼器最後的隱藏態 encoder_state 對其進行初始化。在圖 2 中,我們將源詞「student」中的隱藏態傳遞到了解碼器。

# Build RNN cell
decoder_cell = tf.nn.rnn_cell.BasicLSTMCell(num_units)
# Helper
helper = tf.contrib.seq2seq.TrainingHelper(
decoder_emb_inp, decoder_lengths, time_major=True)# Decoder
decoder = tf.contrib.seq2seq.BasicDecoder(
decoder_cell, helper, encoder_state,
output_layer=projection_layer)# Dynamic decoding
outputs, _ = tf.contrib.seq2seq.dynamic_decode(decoder, ...)
logits = outputs.rnn_output

此處代碼的核心是 BasicDecoder、獲取 decoder_cell(類似於 encoder_cell) 的 decoder、helper 以及之前作為輸入的 encoder_state。

通過分離 decoders 和 helpers,我們能重複使用不同的代碼庫,例如 TrainingHelper 可由 GreedyEmbeddingHelper 進行替換,來做貪婪解碼。

最後,我們從未提到過的 projection_layer 是一個密集矩陣,將頂部的隱藏態轉變為維度 V 的邏輯向量。我們在圖 2 的上部展示了此過程。

projection_layer = layers_core.Dense(
tgt_vocab_size, use_bias=False)

4.損失

給出以上的 logits,可計算訓練損失:

crossent = tf.nn.sparse_softmax_cross_entropy_with_logits(
labels=decoder_outputs, logits=logits)
train_loss = (tf.reduce_sum(crossent * target_weights) /
batch_size)

以上代碼中,target_weights 是一個與 decoder_outputs 大小一樣的 0-1 矩陣。該矩陣將目標序列長度以外的其他位置填充為標量值 0。

我們需要指出來的是,訓練損失可以由 batch_size 分割,因此我們的超參數 batch_size 是「不變數」。也有些人將訓練損失按照 batch_size * num_time_steps 分割,這樣可以減少短句所造成的誤差。更巧妙的,我們的超參數(應用於前面的方法)不能用於後面的方法。例如,如果兩種方法都是用學習率為 1.0 的隨機梯度下降,後面的方法將更有效地利用一個較小的學習率,即 1 / num_time_steps。

5.梯度計算和優化

現在是時候定義我們的 NMT 模型的前向傳播了。計算反向傳播只需要寫幾行代碼:

# Calculate and clip gradients
parameters = tf.trainable_variables()
gradients = tf.gradients(train_loss, params)
clipped_gradients, _ = tf.clip_by_global_norm(
gradients, max_gradient_norm)

訓練 RNN 的一個重要步驟是梯度截斷(gradient clipping)。這裡,我們使用全局範數進行截斷操作。最大值 max_gradient_norm 通常設置為 5 或 1。最後一步是選擇優化器。Adam 優化器是最常見的選擇。我們還要選擇一個學習率,learning_rate 的值通常在 0.0001 和 0.001 之間,且可設置為隨著訓練進程逐漸減小。

# Optimization
optimizer = tf.train.AdamOptimizer(learning_rate)
update_step = optimizer.apply_gradients(
zip(clipped_gradients, params))

在我們的實驗中,我們使用標準的隨機梯度下降(tf.train.GradientDescentOptimizer),並採用了遞減的學習率方案,因此也就有更好的性能。

開始訓練 NMT 模型

讓我們開始訓練第一個 NMT 模型,將越南語翻譯為英語。代碼的入口是** **nmt.py。

我們將使用小規模的 Ted 演講並行語料庫(133k 的訓練樣本)進行訓練。所有的數據都可從以下鏈接找到:https://nlp.stanford.edu/projects/nmt/。

我們將使用 tst2012 作為開發數據集,tst 2013 作為測試數據集。運行以下命令行下載數據訓練 NMT 模型:

nmt/scripts/download_iwslt15.sh /tmp/nmt_data

運行以下命令行開始訓練:

mkdir /tmp/nmt_model
python -m nmt.nmt
--src=vi --tgt=en
--vocab_prefix=/tmp/nmt_data/vocab
--train_prefix=/tmp/nmt_data/train
--dev_prefix=/tmp/nmt_data/tst2012
--test_prefix=/tmp/nmt_data/tst2013
--out_dir=/tmp/nmt_model
--num_train_steps=12000
--steps_per_stats=100
--num_layers=2
--num_units=128
--dropout=0.2
--metrics=bleu

以上命令行訓練一個 2 層的 LSTM seq2seq 模型,帶有 128-dim 的隱藏單元和 12 個 epochs 的嵌入。我們使用 0.2(或然率為 0.8)的 dropout 值。如果沒誤差,在我們訓練中隨著降低混淆度,我們應該能看到類似於以下的 logs。

# First evaluation, global step 0
eval dev: perplexity 17193.66
eval test: perplexity 17193.27
# Start epoch 0, step 0, lr 1, Tue Apr 25 23:17:41 2017
sample train data:
src_reverse: & & ?i?u ?ó , d? nhiên , là cau chuy?n trích ra t? h?c thuy?t c?a Karl Marx .
ref: That , of course , was the & distilled from the theories of Karl Marx . & & &
epoch 0 step 100 lr 1 step-time 0.89s wps 5.78K ppl 1568.62 bleu 0.00
epoch 0 step 200 lr 1 step-time 0.94s wps 5.91K ppl 524.11 bleu 0.00
epoch 0 step 300 lr 1 step-time 0.96s wps 5.80K ppl 340.05 bleu 0.00
epoch 0 step 400 lr 1 step-time 1.02s wps 6.06K ppl 277.61 bleu 0.00
epoch 0 step 500 lr 1 step-time 0.95s wps 5.89K ppl 205.85 bleu 0.00

更多細節,請查看:train.py。

我們可以使用 Tensorboard 在訓練過程中查看模型的總結:

tensorboard --port 22222 --logdir /tmp/nmt_model/

通過以下簡單的變化,就能逆向完成英語到越南語的翻譯。

--src=en --tgt=vi

推理——如何生成翻譯

當你訓練你的 NMT 模型時(並且一旦你已經訓練了模型),可以在給定之前不可見的源語句的情況下獲得翻譯。這一過程被稱作推理。訓練與推理之間有一個明確的區分(測試):在推理時,我們只訪問源語句,即 encoder_inputs。解碼的方式有很多種,包括 greedy 解碼、採樣解碼和束搜索解碼(beam-search)。下面我們討論一下 greedy 解碼策略。

其想法簡單,我們將在圖 3 中作說明:

  1. 在訓練獲取 encoder_state 的過程中,我們依然以相同方式編碼源語句,並且 encoder_state 用於初始化解碼器。
  2. 一旦解碼器接收到開始符 &(在我們的代碼中指 tgt_sos_id),就開始解碼處理(翻譯)。
  3. 最大的單詞,其 id 與最大的 logit 值相關聯,正如被發出的詞(這是 greedy 行為)。例如在圖 3 中,單詞 moi 在第一個解碼步中具有最高的翻譯概率。接著我們把這一單詞作為輸入饋送至下一個時間步。
  4. 這一過程會持續到這句話的終止符「&」,然後輸出(在我們的代碼中是 tgt_eos_id)。

圖 3. Greedy 解碼——一個實例:已訓練的 NMT 模型如何使用 greedy 搜索為源語句 Je suis étudiant 生成翻譯。

推理與訓練的區別在於步驟 3。推理不總是饋送作為輸入的正確目標詞,而是使用被模型預測的單詞。下面是實現 greedy 解碼的代碼。它與訓練解碼器非常相似。

# Helper
helper = tf.contrib.seq2seq.GreedyEmbeddingHelper(
embedding_decoder,
tf.fill([batch_size], tgt_sos_id), tgt_eos_id)
# Decoder
decoder = tf.contrib.seq2seq.BasicDecoder(
decoder_cell, helper, encoder_state,
output_layer=projection_layer)# Dynamic decoding
outputs, _ = tf.contrib.seq2seq.dynamic_decode(
decoder, maximum_iterations=maximum_iterations)
translations = outputs.sample_id

我們在本文中使用了 GreedyEmbeddingHelper 而不是 TrainingHelper。由於無法提前知道目標語句的長度,我們使用 maximum_iterations 限制翻譯的長度。一個啟發是解碼最多兩倍的源語句長度。

maximum_iterations = tf.round(tf.reduce_max(source_sequence_length) * 2)

我們已經訓練了一個模型,現在可以創建一個推理文件並翻譯一些語句:

cat &> /tmp/my_infer_file.vi# (copy and paste some sentences from /tmp/nmt_data/tst2013.vi)

python -m nmt.nmt
--model_dir=/tmp/nmt_model
--inference_input_file=/tmp/my_infer_file.vi
--inference_output_file=/tmp/nmt_model/output_infer

cat /tmp/nmt_model/output_infer # To view the inference as output

注意上述指令也可在模型被訓練時運行,只要存在一個訓練檢查點。詳見 inference.py。

中級

在訓練了一些最基本的序列到序列模型之後,我們現在更進一步。為了打造當前最優的神經機器翻譯系統,我們需要更多的秘訣:注意力機制。該機制由 Bahdanau 等人在 2015 年首次提出(https://arxiv.org/abs/1409.0473),稍後 Luong 等人和其他人完善了它,其核心思想是當我們翻譯時通過「注意」相關的源內容,建立直接的短連接。注意力機制的一個很好副產品是源語句和目標語句之間的一個易於可視化的對齊矩陣(如圖 4 所示)。

圖 4. 注意力可視化——源語句與目標語句之間對齊的實例。圖片來自 2015 年 Bahdanau 等人的論文。

請記住在 vanilla 序列到序列模型中,當開始編碼處理時,我們把最後的源狀態從編碼器傳遞到解碼器。這對短、中長度的語句效果很好;對於長句子,單一固定大小的隱狀態成為了信息瓶頸。注意力機制沒有擯棄源 RNN 中計算的所有隱狀態,而是提出了允許解碼器窺探它們的方法(把它們看作是源信息的動態存儲)。如此,注意力機制提升了長句的翻譯質量。現在,注意力機制實至名歸,已成功應用於其他諸多任務(比如語音識別)。

注意力機制背景

我們現在描述一下注意力機制的實例(Luong et al., 2015),它已經被應用到幾個最新型的系統當中了,包括開源工具,比如 OpenNMT(http://opennmt.net/about/)和此教程中的 TF seq2seq API。我們還將會提供注意力機制相關變體的內容。

圖 5. 注意力機制——基於注意力的 NMT 系統(Luong et al., 2015 中有具體描述)。我們重點詳解注意力計算過程中的第一步。為了更加清晰,我們沒有展示圖(2)中的嵌入層和投影層。

如圖 5 所示,注意力計算髮生在解碼步驟中的每一步。它包含下列步驟:

  1. 當前目標隱蔽狀態和所有源狀態(source state)進行比較,以導出權重(weight),見圖 4。
  2. 基於注意力權重,我們計算了一個背景向量(context vector),作為源狀態的平均權值。
  3. 將背景向量與當前目標隱蔽態進行結合以生成最終的注意力向量。
  4. 此注意力向量將作為下一時序步驟的輸入。前三個步驟可以由下列公式總結:

這裡,函數 score 用於將目標隱蔽狀態 ht 和每一個源狀態 hs 進行比較,結果會被標準化成生成式注意力權重(一個源位置的分布)。其實有很多種關於評分函數(scoring function)的選擇;比較流行的評分函數包括公式(4)中給出的乘法與加法形式。一旦被計算,注意力向量 at 就會用於推導 softmax logit 和損失。這與 vanilla seq2seq 模型頂層的目標隱蔽態相似。函數 f 也可以利用其它形式。

注意力機制的多種實現方法可由以下鏈接獲得:https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/seq2seq/python/ops/attention_wrapper.py。

注意力機制中有什麼相關注意事項呢?

上述公式表明注意力機制有很多種變體。這些變體依賴於評分函數(scoring function)和注意力函數(attention function)的形式,也依賴於前一狀態 ht-1,而不依賴於開始建議的評分函數 ht(Bahdanau et al., 2015)。實際上我們發現的只有一些選擇上的注意事項。一,注意力的基本形式,例如,目標和源之間的直接聯繫需要被呈現。二,把注意力向量輸入給下一時間步驟,以把之前的注意力決策告知給網路(Luong et al., 2015)。最後,評分函數的選擇經常可以造成不同的性能表現。

Attention Wrapper API

在我們的 Attention Wrapper API 的實現中,借鑒了 Weston et al., 2015 在 onmemory network 工作中的術語。相比於擁有可讀、可寫的記憶,此教程中的 attention 機制僅是可讀的記憶。特別是對隱藏態(或者隱藏態的變體,例如 $$Woverline{h}_s$$ in Luong"s scoring style or $$W_2overline{h}_s$$ ) 的設定,被認為是「記憶」。在每個時間步下,我們使用現有的目標隱藏態作為「query」決定讀取哪一部分記憶。通常情況下,query 需要與單個記憶條相對應的 keys 進行對比。在上面對注意機制的演示中,我們偶然使用一套源隱藏態(或者其變體,例如$$W_1h_t$$)作為「key」。你們可以從這種記憶網路術語中獲取靈感,找到其他形式的 attention。

由於 attention wrapper,就不再需要擴展我們帶有 attention 的 vanilla seq2seq 代碼。這部分文件為 attention_model.py。

首先,我們需要定義一種注意機制,例如採用 Luong et al., 2015 的研究。

# attention_states: [batch_size, max_time, num_units]
attention_states = tf.transpose(encoder_outputs, [1, 0, 2])
# Create an attention mechanism
attention_mechanism = tf.contrib.seq2seq.LuongAttention(
num_units, attention_states,
memory_sequence_length=source_sequence_length)

在之前的 Encoder 部分,encoder_outputs 是一套頂層的掩藏態源,形式為 [max_time, batch_size, num_units](因為我們使用 dynamic_rnn with time_major 設定)。在注意機制上,我們需要保證通過的「memory」是批次為主的,所以需要調換 attention_states。我們通過 source_sequence_length 保證注意機制的權重有適當的規範化(只在 non-padding 的位置)。定義完注意機制之後,我們使用 AttentionWrapper 來包裹解碼單元。

decoder_cell = tf.contrib.seq2seq.AttentionWrapper(
decoder_cell, attention_mechanism,
attention_layer_size=num_units)

剩下的代碼基本和編碼器一轉樣 (https://github.com/tensorflow/nmt#decoder)!

上手—打造一個基於注意力的 NMT 模型

為了使注意力發揮作用,我們需要用到 luong、scaled_luong、bahdanau 或 normed_bahdanau 其中的一個作為訓練期間注意力標誌(attention flag)的值。該標誌指定了我們將要使用的注意力機制。除此之外,我們需要為注意力模型創建一個新目錄,因此無需重新使用之前訓練的基本 NMT 模型。

運行以下指令開始訓練:

mkdir /tmp/nmt_attention_model

python -m nmt.nmt
--attention=scaled_luong
--src=vi --tgt=en
--vocab_prefix=/tmp/nmt_data/vocab
--train_prefix=/tmp/nmt_data/train
--dev_prefix=/tmp/nmt_data/tst2012
--test_prefix=/tmp/nmt_data/tst2013
--out_dir=/tmp/nmt_attention_model
--num_train_steps=12000
--steps_per_stats=100
--num_layers=2
--num_units=128
--dropout=0.2
--metrics=bleu

訓練之後,我們可以使用帶有新 model_dir 的相同推理指令進行推理:

python -m nmt.nmt
--model_dir=/tmp/nmt_attention_model
--inference_input_file=/tmp/my_infer_file.vi
--inference_output_file=/tmp/nmt_attention_model/output_infer

基準

IWSLT 英語-越南語

訓練:133k 的樣本,dev=tst2012,test=tst2013

訓練速度:在英偉達 K40m 上是 0.37s 的時間步、15.3k 的 wps,在 Titan X 上是 0.17 s 的時間步,32.2k 的 wps.。

WMT 德語-英語

訓練:4.5M 的樣本量,dev=newstest2013,test=newtest2015

訓練速度:在英偉達 K40m 上是 2.1s 的時間步,3.4k 的 wps,在英偉達 Titan X 上是 0.7s 的時間步,8.7k 的 wps。

為了查看 GNMT 注意的加速度,我們只在 K40m 上做了基準測試:

WMT 英語-德語 全對比

第二行是我們 GNMT 注意模型:模型 1(4 層),模型 2(8 層)。

其他資源

若想深入了解神經機器翻譯和序列-序列模型,我們非常推薦以下資源:

  • Neural Machine Translation and Sequence-to-sequence Models: A Tutorial:https://arxiv.org/abs/1703.01619
  • Neural Machine Translation - Tutorial ACL 2016:https://sites.google.com/site/acl16nmt/
  • Thang Luong"s Thesis on Neural Machine Translation:https://github.com/lmthang/thesis

用於構建 seq2seq 模型的工具很多:

  • Stanford NMT https://nlp.stanford.edu/projects/nmt/ [Matlab]
  • tf-seq2seq https://github.com/google/seq2seq [TensorFlow]
  • Nemantus https://github.com/rsennrich/nematus [Theano]
  • OpenNMT http://opennmt.net/ [Torch]

參考內容

[1] Sequence to sequence learning with neural networks (https://papers.nips.cc/paper/5346-sequence-to-sequence-learning-with-neural-networks.pdf), Ilya Sutskever, Oriol Vinyals, and Quoc V. Le. NIPS, 2014.

[2] Learning phrase representations using RNN encoder-decoder for statistical machine translation (http://aclweb.org/anthology/D/D14/D14-1179.pdf), Kyunghyun Cho, Bart Van Merrienboer, Caglar Gulcehre, Dzmitry Bahdanau, Fethi Bougares, Holger Schwenk, and Yoshua Bengio. EMNLP 2014.

[3] Neural machine translation by jointly learning to align and translate (https://arxiv.org/pdf/1409.0473.pdf), Dzmitry Bahdanau, Kyunghyun Cho, and Yoshua Bengio. ICLR, 2015.

[4] Effective approaches to attention-based neural machine translation (https://arxiv.org/pdf/1508.04025.pdf), Minh-Thang Luong, Hieu Pham, and Christopher D Manning. EMNLP, 2015.

[5] Google『s Neural Machine Translation System: Bridging the Gap between Human and Machine Translation (http://arxiv.org/abs/1609.08144),2016.

本文首發於機器之心(almosthuman2014),如需轉載,請私信聯繫,

此教程的詳細和精確的內容請查看項目:原網站。


  • 自動駕駛小車

RyanZotti/Self-Driving-Car
Ryan Zotti基於Raspberry Pi, OpenCV, TensorFlow實現了一個mini版的自動駕駛小車。

  • 生成音樂

tensorflow/magenta
magenta是Google Brain team的一個project。基於TensorFlow實現自動生成音樂。

  • 圖像識別

tensorflow/tensorflow
其中最廣為人知的example應該是文檔上也用到了的——基於MNIST數據集的手寫數字識別。

  • 語音識別

pannous/tensorflow-speech-recognition
Speech recognition using the tensorflow deep learning framework, sequence-to-sequence neural networks

  • 語言模型

https://github.com/hunkim/word-rnn-tensorflow
Multi-layer Recurrent Neural Networks (LSTM, RNN) for word-level language models in Python using TensorFlow.

  • 人體行為識別

guillaume-chevalier/LSTM-Human-Activity-Recognition
基於TensorFlow的LSTM RNN人體行為識別。

  • 定理證明

tensorflow/deepmath
The Deepmath project seeks to improve automated theorem proving using deep learning and other machine learning techniques.

  • 拿來玩馬里奧賽車

kevinhughes27/TensorKart: self-driving MarioKart with TensorFlow

實現馬里奧賽車的自動駕駛。這個腦洞。

----------------奇怪的分割線= = 快要midterm了我要去複習了複習完再來更----------------


過年時候做了個 識別並屏蔽廣告的服務小項目。主要是用mitproxy來截獲返回的圖片請求,然後利用在google提供的一個模型retrain後的模型檢測這個圖片是不是廣告圖片,是則不返回,達到屏蔽廣告效果

項目地址 https://github.com/Hsiny/Ad-blocker

識別效果還不錯,主要有一個問題是有些圖片的環境問題,比如淘寶上的商品圖片在淘寶肯定不是廣告,但是這個圖片在別的網站的話就可能是廣告了。這個暫時還沒想到方法解決


可以用來解著名小學生面試題fizzbuzz

(註:正確率高達90%)

http://joelgrus.com/2016/05/23/fizz-buzz-in-tensorflow/


talk is cheap,show you the code

https://github.com/jtoy/awesome-tensorflow


當然是對抗生成網路。lsgan,infogan ,cgan,wgan這些復現都很有意思。在進階可以做圖像到圖像的轉換。比如輸入簡筆畫,輸出真實圖像,真實頭像輸齣卡通頭像。


FaceRank-人臉打分基於 TensorFlow 的 CNN 模型,這個妹子顏值幾分? FaceRank 告訴你!《周末小福利》

圖片來自網路,侵權刪。

機器學習是不是很無聊,用來用去都是識別字體。能不能幫我找到顏值高的妹子,順便提高一下姿勢水平。

FaceRank 基於 TensorFlow CNN 模型,提供了一些圖片處理的工具集,後續還會提供訓練好的模型。給 FaceRank 一個妹子,他給你個分數。

從此以後篩選簡歷,先把頭像顏值低的去掉;自動尋找女主顏值高的小電影;自動關注美女;自動排除負分滾粗的相親對象。從此以後升職加薪,迎娶白富美,走上人生巔峰。

知乎專欄:FaceRank-人臉打分基於 TensorFlow 的 CNN 模型,這個妹子顏值幾分? FaceRank 告訴你!《周末小福利》

GitHub:fendouai/FaceRank


謝 @徐悅 邀。

TensorFlow能做很多事情:

1. 它是深度學習框架中,入門成本最簡單的。

2. 圖像方面:圖像分類、物體檢測……

3. 語音方面:語音識別、智能對話機器人、語言翻譯……

4. 圖像和語音結合:看圖說話……

而且,由於有Keras等第三方庫,實現起來也就2、3十行代碼完事,寫一個模型再也不用費勁編碼了。

我最近正在待出版一本《TensorFlow入門》的書籍,淺顯易懂,希望把你領進深度學習的大門,教你做各種人臉識別、語音識別的事情,希望能縮短你進入人工智慧的門檻。


利用RNN將圖片描述成短故事。

ryankiros/neural-storyteller: A recurrent neural network for generating little stories about images


我想這兩篇博文可以很好地幫到您:
深度理解TensorFlow框架,編程原理 ------ 第一講 抽象編程模型
深度理解TensorFlow框架,編程原理 —— 第二講 編程介面和可視化工具TensorBoard


最新的是...幫視頻里的人換臉 例如 某些電影里的女主角 換成你女神的臉 詳情可以去搜索deepfakes...


做一個人臉識別軟體,識別老闆經過時自動切換屏幕


如果是0基礎或剛剛入門,可以用Keras感受下(基於TF高層封裝)。 最酷的是,在訓練過程中對遊戲進行了可視化,如此我們可以觀看它學習,神奇吧(看著小木棍幾欲歪倒……)

:10行命令感受機器學習的神奇(0基礎小白適用) - 知乎專欄


可以跟一些IoT設備做連接,這裡有個video,覆蓋了TensorFlow在raspberry、android、ios上的應用。

http://v.youku.com/v_show/id_XMjc3ODA2MzY3Mg==.html


從文字反向生成圖片,使用對抗網路,最近也有了新突破,代碼位置:

WassersteinGAN/README.md at master · martinarjovsky/WassersteinGAN · GitHub - 故事貼


(′???)σ韓國女星的人臉識別


用notepad可以做什麼有意思的事?


這是真正的大問題,不能局限在賺錢上尋找答案。


推薦閱讀:

如何看待 Google 說已經停用 Map Reduce 好多年?
Google Zeitgeist 2013 視頻回顧了哪些年度事件?
如何看待Google的Cloud Spanner?
為什麼 Google 要用 Sundar Pichai 接替 Andy Rubin 成為 Android 項目負責人?
如何才能獲得 Inbox by Gmail 的邀請碼?

TAG:人工智慧 | 谷歌Google | 有意思 | 神經網路 | TensorFlow |