RIID知識追蹤(一)基於NN方法的SAKT模型(含論文及代碼實現)

2021-03-02 kaggle數據分析

RIID!Answer Correctness Prediction比賽是kaggle上近期比較火的比賽,比賽的任務是根據學生的學習行為,預測其下一次的答題情況,這是一個知識追蹤(Knowledge Tracing)任務。

前言

目前,知識追蹤算法主要分類兩大類:(1)基於Markov模型的BKT,(2)基於深度學習的DKT類模型。

相對於BKT,基於深度學習的DKT類算法,因為算法實現更簡單,同時因為深度學習模型能夠更好的捕捉到用戶學習行為中更深層次的一些特徵,所以效果更好。下圖可以很直觀的看出來,DKT算法明顯優於BKT算法。

2015年,Deep Knowledge Tracing這篇論文首次將知識追蹤任務轉換為Seq-to-Seq的任務,並用RNN實現,取得的跨越式的進展。但是,由於DKT用的是RNN,局限性還比較大。

2019年,A Self-Attentive model for Knowledge Tracing這篇論文用Self-Attention模型取代了RNN,取得了更好的性能。同時,後期基於Transformer類的一些論文,可以說都是在SAKT的基礎上進行改進的,因此本篇文章主要是根據論文用pytorch實現模型。

1 數據準備

Knowledge Tracing任務有一些開源的數據集:Synthetic、Assistments、Junyi和Ednet等。下圖是Ednet論文中對比數據集的數據情況。

Kaggle上的RIID比賽是EdNet同一個機構發布的,所以數據內容上差不多。

數據準備很簡單,就不講太多,直接看代碼就可以了。

我們需要將數據進行預處理,每個學生的學習記錄利用group by合併為序列。

# group by
group = train_df[['user_id', 'content_id', 'answered_correctly']].groupby('user_id').apply(lambda r: (
r['content_id'].values,
r['answered_correctly'].values))

經過Group by操作後,每個學生都有與之對應的學習記錄。然後需要將問題和答案進行padding補全,並將{q、qa}編碼為模型的輸入。其中:q為問題{content_id},qa為學生在本問題上的回答情況{0,1}

Dataset代碼如下,關鍵的幾步是:

(1)初始化,每個用戶對應一組訓練數據,用戶集就是整個數據集的大小。

(2)q、qa進行左側padding,對齊到最長序列,不足補全,超出選取最近的100次學習行為

(3)q、qa進行編碼,如果qa==0,則x=q,如果qa==1,則x=q + n_skill。(目的是對q、qa進行one-hot編碼)

class SAKTDataset(Dataset):
def __init__(self, group, n_skill, max_seq=100):
super(SAKTDataset, self).__init__()
self.max_seq = max_seq
self.n_skill = n_skill
self.samples = group

self.user_ids = [x for x in group.index]

def __len__(self):
return len(self.user_ids)

def __getitem__(self, index):
user_id = self.user_ids[index]
q_, qa_ = self.samples[user_id]
seq_len = len(q_)

q = np.zeros(self.max_seq, dtype=int)
qa = np.zeros(self.max_seq, dtype=int)
if seq_len >= self.max_seq:
q[:] = q_[-self.max_seq:]
qa[:] = qa_[-self.max_seq:]
else:
q[-seq_len:] = q_
qa[-seq_len:] = qa_

target_id = q[1:]
label = qa[1:]

x = np.zeros(self.max_seq-1, dtype=int)
x = q[:-1].copy()
x += (qa[:-1] == 1) * self.n_skill

return x, target_id, label

2 模型定義

SAKT模型結構很簡單,模型輸入學生的學習記錄 ,模型輸出下一次測試 的結果。

模型的輸入是用戶的0~k-1次的學習行為:

(1)x:{i1, i_k-1},經過編碼後的學習表現

(2)question:{e1, e_k}

輸出是用戶第K次的表現:

(1)r_k:{0,1}

模型如下圖,主要由:Embedding layer、Self-attention layer、Feed Forward layers、Prediction layer組成。

2.1 Embedding layer

Embedding層將輸入的題目信息和答題信息編碼為Embedding矩陣。

SAKT有倆個矩陣,M和E。M是Interaction embedding,並加入Position encoding,E是exercise矩陣。

# 定義
self.embedding = nn.Embedding(2*n_skill+1, embed_dim)
self.pos_embedding = nn.Embedding(max_seq-1, embed_dim)

self.e_embedding = nn.Embedding(n_skill+1, embed_dim)

# 計算
x = self.embedding(x)
pos_id = torch.arange(x.size(1)).unsqueeze(0).to(device)
pos_x = self.pos_embedding(pos_id)
x = x + pos_x

e = self.e_embedding(question_ids)

2.2 Self-attention layer

Self-attention layer採用scaled dotproduct attention mechanism。

Self-attention的query、key和value分別為:

# 定義
self.multi_att = nn.MultiheadAttention(embed_dim=embed_dim, num_heads=8, dropout=0.2)

# 計算
att_output, att_weight = self.multi_att(e, x, x, attn_mask=att_mask)

2.3 Feed Forward layer

用一個簡單的前向傳播網絡將self-attention的輸出進行前向傳播。

# 定義
class FFN(nn.Module):
def __init__(self, state_size=200):
super(FFN, self).__init__()
self.state_size = state_size

self.lr1 = nn.Linear(state_size, state_size)
self.relu = nn.ReLU()
self.lr2 = nn.Linear(state_size, state_size)
self.dropout = nn.Dropout(0.2)

def forward(self, x):
x = self.lr1(x)
x = self.relu(x)
x = self.lr2(x)
return self.dropout(x)

self.ffn = FFN(embed_dim)

# 計算
x = self.ffn(att_output)

2.4 Prediction layer

self-attention的輸出經過前向傳播後得到矩陣F,預測層是一個全連接層,最後經過sigmod激活函數,輸出每個question的概率。

x = self.pred(x)
pred = torch.Sigmoid(x)

3 模型訓練

模型的目標是預測用戶答題的對錯情況,利用cross entropy loss計算(y_true, y_pred)。

優化器選擇Adam,learning_rate設置為0.001。

optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
criterion = nn.BCELoss()

4 模型驗證

因為是Kaggle上舉辦的比賽,我們直接將結果提交到kaggle平臺,在平臺的測試集上查看模型的auc。

kernel已經開源:https://www.kaggle.com/wangsg/a-self-attentive-model-for-knowledge-tracing

總結

RIID的這個比賽是近期非常值得關注的一個比賽,目前在kaggle上公開的方案主要是採用的ML方法,我們復現了SAKT算法,並開放了提交的完整代碼,開放的Baseline模型AUC為0.751,是目前開源KT類模型中效果最好的。

可以根據我開放的baseline做進一步的工作,復現SAINT+等基於Transformer的模型,單模型的AUC可以輕鬆達到0.77+。後期我也會視情況考慮公開性能更好的KT模型。

參考

https://github.com/wsg011/kt

A self-attentive model for knowledge tracing

https://www.kaggle.com/wangsg/a-self-attentive-model-for-knowledge-tracing

既然看到最後了,那感謝點讚分享,謝謝你的鼓勵!

歡迎關注微信公眾號:kaggle數據分析。

相關焦點

  • 如何將深度學習研究論文實現為代碼的幾個要點
    💡這裡是一些高效理解論文的小技巧:如果你是研究論文的初學者,最好在閱讀論文之前閱讀一些與該主題/研究論文相關的博客文章和視頻。這使你的工作更容易。在復現論文時,一定要做筆記,並把重要的地方圈出來,以方便做參考。如果你是研究論文實現的新手,並且在任何地方遇到了困難,那麼嘗試一下開源實現並看看其他人是如何做到這一點的,這不是一個壞主意。
  • 基於模型的嵌入式C代碼的實現與驗證
    實踐表明,該基於模型的設計方法可顯著提高工作效率、縮短研發周期、降低開發成本,並且增加了代碼的安全性與魯棒性,有效降低了產品軟體開發的風險。基於模型的設計就是解決該問題的一種方法。Matlab MBD解決方案可以使用戶方便地穿梭於建模、仿真、驗證與實施之間,而無需重寫代碼或改變軟體環境。經過近幾年的不斷完善,這種方法已經從概念演變成實際應用中重要的開發模式。洛克希德·馬丁、波音、空中巴士、通用汽車、奔馳、西門子、摩託羅拉等公司都有應用MBD技術開發的成功經驗。
  • 【專知-PyTorch手把手深度學習教程04】GAN快速理解與PyTorch實現: 圖文+代碼
    < 一文帶你入門優雅的Pytorch >< 快速理解系列(一): 圖文+代碼, 讓你快速理解CNN>< 快速理解系列(二): 圖文+代碼, 讓你快速理解LSTM>< 快速理解系列(三):
  • 基於機器視覺的典型多目標追蹤算法應用實踐
    視頻目標追蹤算法是機器視覺中一項很實用重要的算法,視頻目標追蹤算法應用場景很廣,比如智能監控、機器人視覺系統、虛擬實境(人體跟蹤)、醫學診斷(細胞狀態跟蹤)等。本文由滴普科技2048團隊AI產品部算法工程師朱曉麗介紹基於機器視覺的典型多目標追蹤算法應用實踐。
  • 賊好理解,這個項目教你如何用百行代碼搞定各類NLP模型
    對於初學者如何把握其核心,並能夠自己用代碼一一實現,殊為不易。如果有人能夠將諸多模型和代碼去粗取精,只保留核心,並能夠「一鍵執行」,對於初學者不啻為天大的福音。等的 13 個重要模型的核心代碼實現。整體而言,基本所有代碼都是作者自己完成的,當然都會借鑑已有的實現。很多模型都同時有 TensorFlow 和 PyTorch 兩種版本,但像 Transformer 和 BERT 等擁有谷歌官方實現的模型,作者只提供了 PyTorch 實現。據作者介紹,隨後他計劃將添加 Keras 版本的實現。
  • 滴普技術薈:基於機器視覺的典型多目標追蹤算法應用實踐
    視頻目標追蹤算法是機器視覺中一項很實用重要的算法,視頻目標追蹤算法應用場景很廣,比如智能監控、機器人視覺系統、虛擬實境(人體跟蹤)、醫學診斷(細胞狀態跟蹤)等。本文由滴普科技2048團隊AI產品部算法工程師朱曉麗介紹基於機器視覺的典型多目標追蹤算法應用實踐。
  • 「PyTorch 學習筆記」3.1 模型創建步驟與 nn.Module
    本章代碼:https://github.com/zhangxiann/PyTorch_Practice/blob/master/lesson3/module_containers.py這篇文章來看下 PyTorch 中網絡模型的創建步驟。網絡模型的內容如下,包括模型創建和權值初始化,這些內容都在nn.Module中有實現。
  • 教你用PyTorch實現「看圖說話」(附代碼、學習資源)
    注意: 本文假定你了解深度學習的基礎知識,以前曾使用CNN處理過圖像問題。解決任務的方法可以把imagecaptioning任務在邏輯上分為兩個模塊——一個是基於圖像的模型,從圖像中提取特徵和細微的差別,另一個是基於語言的模型,將第一個模型給出的特徵和對象翻譯成自然的語句。對於基於圖像的模型而言(即編碼器)我們通常依靠CNN網絡。
  • 附代碼、論文解讀連結
    基於此,自監督學習成為深度學習的研究熱點,旨在從未標記樣本中進行學習,以緩解數據標註困難的問題。自監督學習的目標很簡單,即訓練一個模型使得相似的樣本具有相似的表示,然而具體實現卻困難重重。經過谷歌這樣的諸多先驅者若干年的研究,自監督學習如今已取得一系列的進步與發展。
  • tensorflow圖像識別入門實戰:使用LeNet5模型實現貓狗分類
    LeNet5介紹LeNet-5是一種高效的卷積神經網絡,在論文《Gradient-Based Learning Applied to Document Recognition》中 有詳細的解釋,它在大家熟知的手寫數字識別項目中它得到廣泛地使用。
  • 單目標跟蹤算法:Siamese RPN論文解讀和代碼解析
    1.前言深度學習【目標追蹤】專欄寫過一篇對Siamese FC網絡的解析。接著Siamese網絡在單目標追蹤任務(SOT)上的應用,我們展開對Siamese RPN的論文解讀和代碼解析。提到RPN層,了解雙階段法目標檢測模型(FasterRCNN)的各位必定不會陌生。
  • python代碼實戰 | 用 TensorFlow 實現序列標註:基於bi-LSTM+CRF和字符嵌入實現NER和POS
    聽到單詞向量編碼了單詞之間相似性和意義就是這些時刻之一。 當我開始使用這些新概念時,我對模型的簡單性感到困惑,構建了我的第一個用於情感分析的遞歸神經網絡。 幾個月後,作為法國大學高等理工學院碩士論文的一部分,我正在 Proxem 研究更高級的序列標籤模型。Tensorflow vs Theano  當時,Tensorflow剛剛開源,Theano是使用最廣泛的框架。
  • CMU2018春季課程:神經網絡自然語言處理課程(附PPT和代碼)
    每一節課將介紹自然語言中的一個特定的問題或現象,描述其難以建模的原因,並展示若干用於解決這個問題的模型。 在學習的過程中,課程將涵蓋不同的用於創建神經網絡模型的技術,包括處理可變大小和結構化句子、大數據的高效處理、半監督和無監督學習、結構化預測和多語言建模。
  • 深度學習算法優化:VGG,ResNet,DenseNe 模型剪枝代碼實戰
    深度學習算法優化系列七 | ICCV 2017的一篇模型剪枝論文,也是2019年眾多開源剪枝項目的理論基礎 。這篇文章是從源碼實戰的角度來解釋模型剪枝,源碼來自:https://github.com/Eric-mingjie/network-slimming 。我這裡主要是結合源碼來分析每個模型的具體剪枝過程,希望能給你剪枝自己的模型一些啟發。
  • 從頭開始構建最先進的深度學習模型
    課程簡介介紹道,本課程將從實現矩陣乘法和反向傳播基礎開始,到高性能混合精度訓練,最新的神經網絡架構和學習技術,以及介於兩者之間的所有內容。它涵蓋了許多構成現代深度學習基礎的最重要的學術論文,使用「代碼優先」教學方法,每個方法都從頭開始在 Python 中實現並進行詳解(還將討論許多重要的軟體工程技術)。
  • 基於檢索的聊天機器人的實現
    該博客是由WILDML所寫,就是那個實現TextCNN的博主,因此以這篇文章入手對話系統,希望能在對話系統方向養成良好的代碼風格和研究主線。(參考材料連結見文章末尾)原文的github地址為tensorflow v0.9,有部分的函數已經更改。在實際的運行當中使用的TensorFlow的版本為v1.2,因此做了一些修改,並將修改後的代碼上傳到github地址,歡迎fork和start。
  • MindSpore深度概率推斷算法與概率模型
    ,並在MindSpore上進行代碼的實踐。說回到積分問題,同樣基於貝葉斯公式,我們換種形式來表達:上面也提到了推斷本質上就是求後驗分布,當然概率模型往往會比較複雜,涉及的變量會非常多,若直接精確求解,計算開銷太大,因此需要一些近似計算的方法。本篇文章主要討論基於近似的變分推理(Variational Inference)方法,來解決概率推斷問題。變分推理是什麼呢?為了讓大家通俗的理解,這裡參考 @過小咩 的回答。
  • [論文解讀] 阿里DIEN整體代碼結構
    因為DIEN是在DIN基礎上演化,所以代碼有大部分重複。本文採用的是 https://github.com/mouna99/dien 中的實現。,用於訓練數據、保存模型和測試數據0x02 總體架構首先還是要從論文中摘取架構圖進行說明。
  • 十個生成模型(GANs)的最佳案例和原理 | 代碼+論文
    不同於傳統的獎勵機制,某些AI研究人員希望針對自主學習智能體,提出一種全新的方法。他們將實際的示範數據輸入到智能體,然後智能體從中學習並嘗試模仿相同的動作。在這個模型中,Jonathan Ho和Stefano Ermon提出了一種模仿學習的新方法。一般來說,強化學習通常需要設計一個衡量智能體運動行為的獎勵機制。
  • textCNN論文與原理——短文本分類(基於pytorch和torchtext)
    下面還是結合上一個案例:【深度學習】textCNN論文與原理——短文本分類(基於pytorch)[2],使用torchtext進行文本數據預處理,然後再使用torchtext進行模型分類。關於torchtext的基本使用除了可以參考官方文檔,也可以看看這篇文章:TorchText用法示例及完整代碼[3]。