一、項目相關文檔匯總
二、個人工作報告與總結
這次大作業,我在小組內的工作主要是音樂數據收集處理,后端模塊的實現,以及前端的改造。
一. 數據爬取和處理
由於我們搭建是一個在線音樂網站,所以必然涉及要獲取大量音樂相關的數據,比如音樂專輯,圖片,作者等信息。像音樂文件本身其實是很好爬取的,因為音樂的地址為http://music.163.com/song/media/outer/url? id=加上音樂id信息即可 ,由於我們后來棄用了本地音樂播放,而采用獲取網站的mp3信息而導致我們爬下來的音樂信息,很多是沒有版權播放的,所以又必須要爬取到音樂的完整信息,獲取到該音樂是否有版權,並對其過濾。這其中也涉及到了網易雲很多數據Request HEaders里的Cookie值、FromData里的params、encSecKey都是加密過的,需要查詢資料了解怎么解密,過程很辛苦但也學到了不少東西。
二.前后端交互以及各個模塊的實現
由於對前后端框架了解的比較少,在我們的項目中采用了 js 的 ajax 與 后台 serverlet 的技術路線進行數據的互傳交互。並且為了代碼的簡潔和不必要的冗余,對數據庫操作進行了封裝,讓實際操作中的數據存取與寫入更加方便快捷。
-
發現界面中歌單,mv的添加,歌單歌曲的獲取以及側邊播放列表的實現
在進入發現界面獲取歌單的時候首先通過ajax 向servelet請求數據,數據請求成功后,每一條數據(也就是歌單的數據)都對應一個div,采用左浮動的模式,這樣添加歌單的時候,歌單超過邊界會自動浮動到下面,對每個div都用值為歌單id的data-id標注,這樣在監聽到點擊事件后,就可以很方便從數據庫中獲取到該歌單中的歌曲列表。
在監聽到歌單的點擊事件進入到歌單后,從后端傳到前端的歌曲信息不僅需要在頁面中展示出來,還需要存入到一個全局的列表中(對於我喜歡的歌,最近播放也是同理),這樣在檢測到鼠標的點擊事件以后只要獲取當前點擊列表的相對位置就可以從全局中拿到這首歌進行播放,同時這個全局的歌曲表單還用於可顯示和隱藏播放列表中,使得不管我到了哪個界面都可以選擇上一次播放的音樂列表中的任何歌曲。
-
最近播放、我喜歡的音樂模塊及播放器的改造
為了記錄最近播放的歌曲,不管是用戶模式還是非用戶模式下,當進入coco music 界面時,自動為其創建 一個列表,每當用戶點擊歌曲的時候,獲取到當首歌曲的信息,並將其push到這個最近播放歌曲的列表中即可,當然需要注意當用戶重復播放歌曲的時候,不能讓最近播放表單中有重復的歌曲,而是要讓以往播放的歌曲放在第一位。
我喜歡的音樂則通過播放器欄的愛心點擊事件獲得,在這里為了減少數據庫的操作,當用戶進入coco音樂界面的時候,除了將用戶的喜好歌曲加入我喜歡的音樂界面外,還要自動為其創建一個喜歡音樂的列表,這樣每次打開一首歌,播放欄愛心的紅與不紅的設置不需要每次去數據庫查找,而是直接在js中查找即可,加快界面反應速度。當然,當發生愛心的點擊事件時,也需要在數據庫喜好歌曲表單中添加刪除該歌曲。同時我喜歡的音樂也為音樂推薦模塊打下了基礎。
三.音樂推薦功能實現
本項目的音樂推薦功能采用人工智能的個性化推薦方式,通過對個人的喜好歌單中的歌曲與歌庫中的音樂計算曲風的相似度,使得推薦的歌曲更加符合用戶口味。
-
數據准備
在網易雲web版本中,可以通過歌曲風格選擇歌單。這里我挑選了音樂類型中比較有代表性的古典、爵士、金屬、輕音樂、說唱、鄉村、搖滾、流行、古風 9種類型的音樂。對每個類型的音樂收集了100左右首歌並打上分類標簽。
-
數據處理
首先,從網頁版中爬下來的音樂是.mp3 格式,為了在后面方便生成頻譜圖,將數據轉換為.wav 格式后取出其中一個聲道(由於兩個聲道的頻譜圖十分類似,若都采用則可能使數據重復過多導致模型訓練過擬合而達不到好的效果),並生成整首歌的頻譜圖。頻譜圖如下:
為了便於我們后續模型的搭建(CNN 一般用標准正方形圖輸入)以及數據量的增加,我將一首歌的長頻譜圖切分成了total_length/256 個 256*256 的小頻譜圖,並將多余的數據刪去。於是我們得到了以下處理好的帶標簽訓練數
-
模型搭建
(簡介)CNN網絡主要特點是使用卷積層,其實是模擬了人的視覺神經,單個神經元只能對某種特定的圖像特征產生響應,比如橫向或者縱向的邊緣,本身是非常簡單的,但是這些簡單的神經元構成一層,在層數足夠多后,就可以獲取足夠豐富的特征。
在這里我采用了resnet34 的預訓練模型,由於我們的數據是9個類別的,所以我需要將resnet 的最后一層 fc 替換為輸出為9維的全連接層參與我們數據的訓練。在訓練的過程中對resnet34 的模型進行finetune,使其更好的適應我們的音樂頻譜數據。
以下為模型在測試集上的准確度信息:
隨后將測試集上到達最高准確率的模型保存下來,重新加載模型時去除最后一層的全連接層,使得每張圖片輸入模型后可以得到512維的特征數據,這512維的特征數據可以認為是這首歌的表示。下圖為某一首歌的部分特征信息。
當我們得到了詞庫中所有歌詞的特征表示后,兩首歌之間的相似度可以定義為 sim(x,y) = $ \frac{1}{1+\sqrt{\sum_{i= 1}\left ( x_{i}-y_{i}\right )^{2}}}$
這樣我們就可以根據歌曲的相似度來推薦歌曲了,每當我們coco_music 用戶往自己的 ”喜歡“ 歌單中添加歌曲時,我們將用戶添加的歌曲與其他歌曲進行相似度的計算,進行排序后,取出相似度高於一定閘值的歌或是前幾位的歌對用戶進行推薦。這不同於現在各個音樂平台所用的協同過濾,聚類算法等需要大量的用戶信息才能進行音樂推薦,我們只需要得到用戶的喜好歌曲就可以進行歌曲的推薦。
以下為對”罵醒你“歌曲計算出的詞庫中的相似度排序
當然這里也有一個坑,當用戶的喜好歌曲中,不同的歌曲的推薦中可能會得到一樣的歌曲,這個時候就需要對數據庫進行處理,保證添加推薦歌曲時歌曲的唯一性。
- 效果
四.總結與展望
1. 課程收獲
經歷了本學期的軟件工程課程,不僅讓我從理論上了解軟件工程的概念。並且在個人項目和集體項目的實作中,親身經歷了開發一個完整的軟件需要經歷的種種,讓理論和實踐得到了很好的結合。課程中,我感受到了需求分析的重要性,在開發一套軟件之前,需要完整、清晰、具體的要求,我們這個項目需要做什么,實現哪些功能,做這些功能又是為了什么。作為一名軟件開發者必須深入用戶的實際需求,從用戶的角度思考,開發能讓用戶滿意的軟件。同時,除了軟件的功能性需求,也需要考慮到軟件在不同的運行環境下能夠跑的起來,做出一款”包容性“ 強的軟件也是十分重要的。
2.反思
- 由於這是我們第一個集體開發一個相對比較大的項目,我們需要更加嚴謹的開發流程,需要對項目完成進度進行總體的控制與規划。在項目開始前需要一個總體的計划,到什么時間點我們需要有怎么樣的成果,如果到該時間點延期了,該怎么做。同時,我們需要增加集體高效率開發的時間,增加組員之間的交流合作,而不是自己做自己的。所有大的程序離不開團隊合作,團隊的分工,團隊的合作在整個項目的推進過程中是至關重要的。
- 對項目初期提出的需要,應該按部就班的落實,或是在項目初期思考需求的時候根據實際情況考慮周到,項目的完成度對於整個項目來說也是非常重要的。
3.展望
我們希望本項目不是為了完成軟件工程的大作業而完成,在后面的時間能對軟件還沒有實現的功能進行完善,比如在歌曲推薦的功能上用RNN 加入歌詞的風格信息,讓推薦更加靈活完善。同時也希望在后面的編程開發中更加注重編碼素養,將理論的學習更多的用於實踐之中。
五. 課程感受及建議
- 首先要對課改《構建之法》給予肯定,課程中 “項目驅動”,“以學生為主體,以老師為主導” 的思想讓我們學生能走出課本的框框,以實際項目推動理論知識的學習。
- 課程中老師對現實社會中各個軟件工程相關的故事和自己的看法,擴寬了我們的知識面,活躍了課堂氛圍。
- 在課程教學中,可以適當增加小項目,即使是搭建一個很小的組件也好,同時增加靈活性,給與同學更大的選擇空間,讓我們可以從不同的角度感受軟件工程的意義。
- 對於最后的項目,其實大家都集中在組內的討論與推進,組與組之間的交流和溝通太少了。可以在項目達到一定程度的時候,請每個組分享一下經驗,和當前所遇到的坑。這樣讓大家不僅能從自己的項目中獲取經驗,也能從別的組的歷程與遇到的問題中學習,同時也活躍了課堂氣氛。在分組上,也應該適當照顧一下學生的方向(比如說有些同學對前端懂的多,后端有所欠缺,那么如果6個都會前端的人組在一起可能會導致資源浪費,或是項目推進較慢),同時,也要適當照顧一下在某個方向有所欠缺的同學,讓每一個人都能充分得到互相學習的機會。