8月23日,“2018年全球高校學(xué)生DeeCamp AI訓(xùn)練營”在北大舉行閉幕式,經(jīng)過層層評比,來自全球高校的300學(xué)生組成的28支隊(duì)伍選出了8支優(yōu)勝隊(duì)伍。其中,一只用AI自動生成嘻哈歌詞的隊(duì)伍獲得了“最佳DEMO獎”。
AI寫嘻哈歌詞的水平如何?能達(dá)到以假亂真的地步嗎?不看廣告看療效,我們先來猜猜下面的歌詞哪些是AI寫的:
不是樂理專修 做點(diǎn)兒曲式研究 我們的力量來自宇宙 自己的節(jié)奏不是樂理專修 所有聽的觀眾 打破他們傳統(tǒng) 進(jìn)到環(huán)球 繼續(xù)讓你感受
再來一個:
自己就帶上了有色眼鏡 金錢摧毀多少事情 瓦解你的中樞神經(jīng)自己就帶上了有色眼鏡 我只想把世界分的更清 卻發(fā)現(xiàn)自己卻模糊了心
正確答案是:第一行都是模型生成的,第二行是原作??梢钥闯觯珹I的效果還是不錯的,至少挺押韻的。
那么,這個有嘻哈精神的團(tuán)隊(duì)到底是怎樣搭建這個 AI 模型的?
首先我們需要定義這個問題,也就是根據(jù)一句歌詞迭代生成一段嘻哈歌詞。另外一個是押韻,這是嘻哈歌詞一大特點(diǎn)。
清楚了問題,我們?nèi)フ{(diào)研一下已經(jīng)有的文本聲稱方案,最終把它的優(yōu)點(diǎn)和缺點(diǎn)列出來,然后我們選擇了SequenceGAN作為基礎(chǔ)模型,并且在這個之上提出我們的模型——SequenceGAN。
SequenceGAN 有兩個組件,生成器、判讀器,讓生成器生成足以逼真的歌詞。
我們在這個基礎(chǔ)之上,有一個嘻哈生成網(wǎng)絡(luò)。第一點(diǎn)是在這個之前我們增加了一個編碼網(wǎng)絡(luò),將然后生成一些跟主題相關(guān)的歌詞,第二點(diǎn)是把目標(biāo)函數(shù)修改。
以下是SequenceGAN的效果,它有非常多的重復(fù)的語句,這就是GAN的一個通病,對于不同的輸入,輸出卻很相同。
我們知道嘻哈歌手不可能一句話唱一整首,所以我們調(diào)研了一些文獻(xiàn),并且借鑒今年SentiGAN的想法,對生成器的目標(biāo)函數(shù)進(jìn)行修改,最后效果非常顯著,有一個質(zhì)的變化。
有了多樣化的文本之后,我們下一步要解決的問題就是如何去實(shí)現(xiàn)押韻。我們嘗試兩種方案,一種是基于目標(biāo)函數(shù),增加押韻場景項(xiàng),就好像考試的附加題,做對了給額外得分。但是我們希望它一直能夠去做附加題,實(shí)現(xiàn)押韻的功能。但是它并不能很自主地學(xué)習(xí)到押韻的關(guān)。
最后我們嘗試了基于規(guī)則的方式來實(shí)現(xiàn)這個押韻。比如輸入“你真美麗”,我們根據(jù)這個i的韻腳去構(gòu)建一個向量,做一個簡單的操作,就能夠得到必然是押韻的結(jié)果,同時可以控制押韻的概率。
▌附完整解讀
項(xiàng)目作者:孫蒙新(廈門大學(xué))、項(xiàng)瑞昌(華中科技大學(xué))、伊瑋雯(北京郵電大學(xué))、陸亦揚(yáng)(合肥工業(yè)大學(xué))、石華(西南石油大學(xué))、汪自力(西安電子科技大學(xué))、龐雲(yún)升(重慶大學(xué))、周子群(東北大學(xué))、王超群(北京林業(yè)大學(xué))、詹玨岑(VanderniltUniversity)
1、數(shù)據(jù)
我們一共使用了 10w 條嘻哈歌詞,并且已經(jīng)將一些不符合社會主義核心價值觀的句子標(biāo)注了出來。數(shù)據(jù)的預(yù)處理主要步驟如下:
在對句子進(jìn)行篩選之后,我們利用 Jieba 進(jìn)行分詞,觀察到單句長度集中在 8~10 左右;
在利用 Tensorflow 中的 Tokenizer 進(jìn)行 tokenize 并構(gòu)建 word2idex 字典后,詞表大小在 11000 左右,考慮到這個大小還可以接受,沒有做限制詞表大小的操作;
利用 pad_sequence 將句子 padding 到 20(和 SeqGAN 中相同);
構(gòu)建 x-y pair,利用上一句預(yù)測下一句(導(dǎo)師后來建議可以借鑒用 Skip-gram 的思路,同時預(yù)測上一句和下一句,但沒有時間去嘗試了),分割數(shù)據(jù)集。
訓(xùn)練數(shù)據(jù)地址:
https://drive.google.com/drive/folders/1QrO0JAti3A3vlZlUemouOW7jC3K5dFZr)
2、模型
我們的生成模型的整體基于 SeqGAN,并對其做了一些修改,模型架構(gòu)如下:
主要改動有兩點(diǎn):
1.增加輸入語句的編碼:這一點(diǎn)類似 Seq2Seq 的 Encoder,SeqGAN 原本的 initial state 是全 0 的,為了將上文的信息傳遞給生成器,我們采用了一個簡單的全連接層(Fully Connected Layer),將輸入句子的 Word Embedding 經(jīng)過一個線性變化之后作為生成器的 LSTM。事實(shí)上也可以嘗試使用 RNN(LSTM)來作為 Encoder,不過這樣模型的速度可能會比較慢。
2.將原先 Generator 的 Loss Function 改為 Penalty-based Objective:在訓(xùn)練模型的過程中我們發(fā)現(xiàn),模型在 Adversarial Training 多輪之后出現(xiàn)了嚴(yán)重的 mode collapse 問題,比如:
別質(zhì)疑自己 遮罩錯的消息不要過得消極 世間人都笑我太瘋癲 世間人都笑我太瘋癲 守護(hù)地獄每座墳?zāi)?世間人都笑我太瘋癲你不知道rapper付出多少才配紙醉金迷 世間人都笑我太瘋癲 但卻從來沒有心狠過 如果你再想聽你不知道rapper付出多少才配紙醉金迷 你不知道rapper付出多少才配紙醉金迷
可以看到“世間人都笑我太瘋癲”和“你不知道rapper付出多少才配紙醉金迷”占據(jù)了我們生成的結(jié)果。mode collapse,簡單來說就是輸入的改變不會影響生成的結(jié)果。為此我們調(diào)研了一些 Paper,最終采用了SentiGAN 中提出的 Penalty-based Objective Function:
3、押韻
嘻哈歌詞非常重要的一個特點(diǎn)就是句與句之間的押韻,我們在實(shí)現(xiàn)這一功能的時候嘗試了兩種方案:
1.Reward based,在 reward 函數(shù)上增加額外的押韻獎賞項(xiàng), r(rhyme):對 Generator 的生成的句子和輸入的句子進(jìn)行押韻的判斷,如果押韻,則提供額外的獎賞。
2.Rule-based,生成時只對押韻的詞進(jìn)行采樣:在生成句尾的詞的概率分布時候,通過獲取和輸入句尾押韻的詞,只在這些押韻的詞進(jìn)行采樣。
方法一,如果能夠通過設(shè)計(jì) reward function 就能實(shí)現(xiàn)押韻的功能,那模型就是完全 end2end,非常 fancy 了。但是理想很豐滿,現(xiàn)實(shí)很骨感,經(jīng)過幾天的調(diào)整押韻獎賞的權(quán)重,都沒能看到押韻率(我們設(shè)置的用于檢測押韻獎賞效果的指標(biāo),每個 batch 中和 input 押韻的句子的比例)的上升 。我們懷疑是這種獎賞的結(jié)合會讓 Generator 產(chǎn)生混淆,并不能明確自己 reward 來自何處,應(yīng)該需要更加具體的一些限制才能夠?qū)崿F(xiàn)這一方法。
方法二,一開始我是拒絕這么做的,用基于規(guī)則的方法不是我的理想。但是為了做出產(chǎn)品來,我還是屈服了。但還有一個問題擺在面前:怎么知道生成的是句尾呢?導(dǎo)師提醒我們,我們可以把輸入倒過來。這是 NMT 中常用的一個手段,對于 LSTM,句子是真的還是反的差別不大,即使有差別,也可以通過一個 Bi-LSTM 來捕獲不同順序的信息。而為了知道哪些字詞是押韻的,我們實(shí)現(xiàn)制作了一張 vocab_size x vocab_size 的大表 rhyme,如果兩個詞(index 分別為 i, j)押韻,則 rhyme[i, j] 非 0,否則為 0。
如上圖所示,如果我們的輸入為“你真美麗”,句尾詞為“美麗”,韻腳為 i;最終采樣結(jié)果只會在押韻的詞中采樣,示例的采樣結(jié)果為“春泥”。
據(jù)此,我們就可以對生成過程的第一個詞的詞表分布進(jìn)行一個 mask 操作,使得非押韻的詞的概率都變成 0,就能夠保證押韻了,代碼片段如下:
#獲取input的最后一個詞first_token=self.inputs[:,0]#(batch_size,1)#控制押韻的概率,現(xiàn)在設(shè)置為1.0,即100%押韻select_sampler=Bernoulli(probs=1.0,dtype=tf.bool)select_sample=select_sampler.sample(sample_shape=self.batch_size)#獲取對應(yīng)的index押韻行token_rhyme=tf.cast(tf.gather(self.table,first_token),tf.float32)#進(jìn)行maskprob_masked=tf.where(select_sample,tf.log(tf.multiply(token_rhyme,tf.nn.softmax(o_t))),tf.log(tf.nn.softmax(o_t)))#根據(jù)mask之后的概率分布進(jìn)行采樣next_token=tf.cast(tf.reshape(tf.multinomial(prob_masked,1),[self.batch_size])
不過這個制表的過程比較耗費(fèi)時間(大約跑了 3 個小時,i7)。另一種思路是可以根據(jù)韻腳對字詞進(jìn)行分類,將相同韻腳的詞的 index 編到一起,這樣我們可以通過獲取每個詞的韻腳來知道目標(biāo)詞的范圍,而不用挨個的去判斷是否押韻。
-
AI
+關(guān)注
關(guān)注
87文章
31475瀏覽量
269869 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4345瀏覽量
62867 -
生成器
+關(guān)注
關(guān)注
7文章
319瀏覽量
21080
原文標(biāo)題:AI有嘻哈!
文章出處:【微信號:rgznai100,微信公眾號:rgznai100】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論