0%

20230129-ChatGPT 教我實作 Anki 演算法

ChatGPT 教我實作 Anki 演算法

前言

Anki 演算法一直是我感興趣的主題,但我不知道如何開始實現它。
然而,今天我突然有了靈感,我打算問問 ChatGPT,看看能得到什麼幫助。
那就廢話不多說,直接開始吧!

過程

步驟1

問:

1
我要實作anki演算法,給我c#程式碼,並加上註解

答:

1
2
3
4
5
6
實作 Anki 演算法的 C# 程式碼可能需要一些較複雜的邏輯與結構,因此我無法提供完整的程式碼給您。
然而,我可以給您一些概念和程式碼片段,讓您可以自行實作。
Anki 演算法的核心思想是使用記憶遺忘曲線來決定哪些卡片需要再次學習。
首先,您需要建立一個卡片類別,其中包含關於卡片的所有資訊,如問題和答案。
然後,您需要建立一個學習管理類別,其中包含所有卡片的列表,以及決定哪些卡片需要再次學習的邏輯。
下面是一個簡單的程式碼片段,描述了如何使用記憶遺忘曲線來決定哪些卡片需要再次學習:

此處程式碼先略過,最後再貼完整的版本。

步驟2

問:

1
給我簡單的c#程式範例,實作anki演算法

答:

1
以下是一個簡單的 C# 程式範例,演示如何實作 Anki 演算法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
using System;
using System.Collections.Generic;

class Card
{
public string Question { get; set; }
public string Answer { get; set; }
public int Repetition { get; set; }
public double EFactor { get; set; }
public DateTime NextReview { get; set; }

public Card(string question, string answer)
{
Question = question;
Answer = answer;
Repetition = 0;
EFactor = 2.5;
NextReview = DateTime.Now;
}
}

class Anki
{
private List<Card> _cards;

public Anki()
{
_cards = new List<Card>();
}

public void AddCard(Card card)
{
_cards.Add(card);
}

public void Study()
{
List<Card> cardsToReview = new List<Card>();

foreach (Card card in _cards)
{
if (card.NextReview <= DateTime.Now)
{
cardsToReview.Add(card);
}
}

foreach (Card card in cardsToReview)
{
Console.WriteLine("Question: " + card.Question);
Console.Write("Answer: ");
string answer = Console.ReadLine();

if (answer == card.Answer)
{
card.Repetition++;
card.EFactor = card.EFactor + (0.1 - (5 - card.Repetition) * (0.08 + (5 - card.Repetition) * 0.02));
card.EFactor = Math.Max(1.3, card.EFactor);

if (card.Repetition == 1)
{
card.NextReview = DateTime.Now.AddDays(1);
}
else
{
card.NextReview = DateTime.Now.AddDays((int)(card.EFactor * card.Repetition));
}
}
else
{
card.Repetition = 0;
card.EFactor = 2.5;
card.NextReview = DateTime.Now;
}
}
}
}
1
2
3
4
5
6
7
8
9
程式碼中的 Card 類別表示卡片,它包含問題,答案,重複次數,記憶遺忘曲線的因素值,以及下次檢視的時間。

而 Anki 類別則管理所有卡片的列表,並實作了學習邏輯。

在程式碼中,AddCard 方法用於新增卡片到列表中,Study 方法則實作了 Anki 演算法中的學習邏輯。
在 Study 方法中,先遍歷所有卡片,找出需要檢視的卡片,然後對每張卡片進行檢視,並根據回答正確與否更新卡片的重複次數,記憶遺忘曲線的因素值和下次檢視的時間。

若回答正確,則將重複次數加1,並根據公式計算新的記憶遺忘曲線因素值,並設定下次檢視時間。若回答錯誤,則將重複次數設為0,記憶遺忘曲線因素值設為2.5,並設定下次檢視時間為當前時間。
請注意,這只是一個簡單的範例,並不包含所有 Anki 演算法的細節,如果要實作實際應用,還需要更多的功能與邏輯。

步驟3

問:

1
再詳細說明一下記憶遺忘曲線的原理

答:

1
2
3
4
5
6
7
記憶遺忘曲線是一種描述人類記憶遺忘曲線的統計模型。它是由德國心理學家Hermann Ebbinghaus在1885年提出的。

模型中,每一次記憶一個新的東西都會有一個遺忘曲線,表示記憶這個東西的過程。在過程中,記憶會先快速遞減,之後會慢慢遞減。

遺忘曲線的具體形狀可以用一個經典的指數遺忘曲線模型來描述,其中記憶遺忘程度可以用一個叫做記憶遺忘曲線因素(memory-decay factor)的參數來描述。記憶遺忘曲線因素一般在 0.5 到 2.5 之間,數值越大,記憶遺忘越快。

Anki 演算法就是利用記憶遺忘曲線的原理來設計學習計畫,根據每張卡片上次學習的時間和記憶遺忘曲線因素來計算下次學習時間,達到輕鬆記憶和長期記憶的目的。

步驟4

問:

1
用c#程式碼說明記憶遺忘曲線

答:

1
以下是一個簡單的 C# 程式碼範例,模擬記憶遺忘曲線的過程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using System;

class MemoryDecay
{
// 設定記憶遺忘曲線因素
private double memoryDecayFactor = 0.8;

// 記錄每次學習時的記憶程度
private double[] memory;

public MemoryDecay(int time)
{
memory = new double[time];

// 初始化記憶程度
for (int i = 0; i < time; i++)
{
memory[i] = 1.0;
}
}

public void Update()
{
for (int i = 0; i < memory.Length; i++)
{
// 計算遺忘程度
memory[i] = memory[i] * memoryDecayFactor;
}
}

public void PrintMemory()
{
for (int i = 0; i < memory.Length; i++)
{
Console.WriteLine("Time: " + i + ", Memory: " + memory[i]);
}
}
}
1
2
3
程式中,透過一個記憶遺忘曲線因素 memoryDecayFactor 來模擬記憶遺忘曲線,並將每次學習時的記憶程度儲存在 memory 陣列中。Update() 方法用來更新每次學習時的記憶程度,而 PrintMemory() 方法則用來輸出每次學習時的記憶程度。

範例中的程式碼只是簡單的模擬記憶遺忘曲線,Anki 演算法需要考量更多因素,例如用戶的學習頻率、學習效果等,實際實作上會更複雜。

步驟5

問:

1
回到剛剛的anki程式碼實作,再加上使用者權重的因素,寫成c#程式碼

答:

1
以下是一個簡單的 C# 程式碼範例,實作 Anki 演算法並考慮使用者權重因素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using System;
using System.Collections.Generic;

class AnkiAlgorithm
{
// 儲存單元內容
private class Card
{
public string content;
public double weight;
}

// 設定記憶遺忘曲線因素
private double memoryDecayFactor = 0.8;

// 儲存所有單元
private List<Card> cards = new List<Card>();

public void AddCard(string content, double weight)
{
// 新增單元
Card card = new Card();
card.content = content;
card.weight = weight;
cards.Add(card);
}

public void Update()
{
for (int i = 0; i < cards.Count; i++)
{
// 計算遺忘程度
cards[i].weight = cards[i].weight * memoryDecayFactor;

// 根據權重決定是否需要重新學習
if (cards[i].weight < 0.5)
{
Console.WriteLine("Card: " + cards[i].content + " needs to be reviewed.");
}
}
}
}
1
2
3
程式中首先定義了一個名為 Card 的類別,用來儲存單元內容和權重。AnkiAlgorithm 類別中有一個 cards 陣列用來儲存所有單元,AddCard() 方法用來新增單元,Update() 方法則用來更新每個單元的權重。

範例中的程式碼只是簡單的模擬 Anki 演算法,實際實作上會更複雜,例如需要考量用戶的學習頻率、學習效果等。

步驟6

問:

1
再加上記憶遺忘曲線的功能實作,一樣用c#程式碼表示

答:

1
以下是一個簡單的 C# 程式碼範例,實作 Anki 演算法並考慮使用者權重和記憶遺忘曲線因素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using System;
using System.Collections.Generic;

class AnkiAlgorithm
{
// 儲存單元內容
private class Card
{
public string content;
public double weight;
public DateTime lastReview;
}

// 設定記憶遺忘曲線因素
private double memoryDecayFactor = 0.8;
private double reviewInterval = 0.2;

// 儲存所有單元
private List<Card> cards = new List<Card>();

public void AddCard(string content, double weight)
{
// 新增單元
Card card = new Card();
card.content = content;
card.weight = weight;
card.lastReview = DateTime.Now;
cards.Add(card);
}

public void Update()
{
for (int i = 0; i < cards.Count; i++)
{
// 計算遺忘程度
TimeSpan timeSinceLastReview = DateTime.Now - cards[i].lastReview;
double forgettingCurve = Math.Pow(memoryDecayFactor, timeSinceLastReview.TotalDays / reviewInterval);
cards[i].weight = cards[i].weight * forgettingCurve;

// 根據權重決定是否需要重新學習
if (cards[i].weight < 0.5)
{
Console.WriteLine("Card: " + cards[i].content + " needs to be reviewed.");
}
}
}
}
1
2
3
4
5
6
程式中首先定義了一個名為 Card 的類別,用來儲存單元內容、權重和上次學習時間。AnkiAlgorithm 類別中有一個 cards 陣列用來儲存所有單元,AddCard() 方法用來新增單元,Update() 方法則用來更新每個單元的權重。
程式碼中額外設定了兩個變數 reviewInterval 和 memoryDecayFactor,用來控制記憶遺忘曲線。reviewInterval 表示重新學習的間隔,memoryDecayFactor 表示記憶遺忘速率,它們都可以根據實際情況進行調整。

在 Update() 方法中,程式會遍歷所有單元,計算每個單元的遺忘程度。程式會計算距離上次學習的時間,並使用 Math.Pow() 方法來計算遺忘程度。最後,程式會根據單元的權重來決定是否需要重新學習。

這只是一個簡單的範例,實際的 Anki 演算法可能會更複雜且會有更多的參數可供調整。

評論

由以上的回答,已經得到清楚的方向,未來再找時間做成自己背單字、學技術的工具
看看成果是否滿意

完整過程錄影

同場加映 - sentdex 大神用 ChatGPT Writes a Chatbot AI