近年來 AI 席卷全球,為此本文作者嘗試了近 20 遍,最終用 C++ 建立了一個最簡單易懂的生成式 AI 模型,供感興趣的開發者參考。
原文連結:https://learncplusplus.org/how-to-create-simple-generative-ai-code-in-c/
作者 | Yilmaz Yoru
轉譯 | 鄭麗媛
短短一年多的時間裏,AI 技術發展迅速,其中最引人矚目的實作是 ChatGPT,它基於一種生成式 AI 技術。後來,我們又有了 GPT-4,GPT-5 也正在研發中。
在各種文本和影像公開測試中,人們普遍認為生成式 AI 是一項非常有創造力的技術。事實上,生成式 AI 是 AI 領域深度學習的一個分支,而所有這些看似神奇的技術背後,都要歸功於大量的數學知識。在本文中,我們將編寫一些非常簡單的 C++ 程式碼,從給定的輸入中學習,並生成隨機輸出。
什麽是 AI?
人工智慧(Artificial Intelligence)又稱 AI,是指在機器中模擬人類智慧,透過編程使其看起來像人類一樣思考並模仿人類行為。這個術語也可用於任何表現出與人類思維相關的特征(如學習和解決問題)的機器。如果你想了解更多 AI 的相關術語,可以查閱我之前寫的這篇文章:【AI 技術:C++ 人工智慧入門】 (https://learncplusplus.org/ai-techs-introduction-to-artificial-intelligence-in-c/) 。
什麽是生成式 AI?
生成式 AI(Generative AI、GenAI 或 GAI)是一種 AI 技術,透過生成模型來生成文本、影像、視訊或其他數據。生成式 AI 模型透過接受給定的輸入(比如文本、影像或數據集)進行學習,然後用生成式模型對這些輸入進行訓練,進而生成新的輸出範例,甚至可以在沒有任何人類指示的情況下生成新的內容。
一般來說,使用者給出簡單的指令(即「提示」),然後它就會根據這些指令和訓練好的數據集生成一個新的樣本。下面是一個簡單的生成式 AI 模型的範例。
有一些生成式 AI 模型包括:生成對抗網路(GANs)、變分自編碼器(VAEs)、自回歸模型和變換器(Transformer)。
如何用 C++ 建立簡單的生成式 AI 模型?
首先,我們來建立一個簡單的生成式 AI,它可以透過給定的文本輸入進行訓練並從中學習。然後,我們可以建立一個生成模型來生成新的句子。在這裏,我們將會有一個擁有對映的類,而該對映將保存字串以及與每個字串相關的字串。下面,讓我們來定義類和對映。
class GenerativeAI
{
private:
std::map<std::string, std::vector<std::string>> wordRel; // map to world releation
public:
}
我們可以透過將它們添加到字串向量中來教授單詞之間的關系。請註意,這是一個非常簡單的學習範例,在真正的生成式 AI 模型中,你應該考慮更多細節,並且可以透過不同啟用函式模型中的權重進行訓練。更復雜的專業模型有更多層、偏置、隱藏神經元、過濾器、變換器(Transformer)、張量模型等。
接下來,讓我們建立一個可以從給定文本中學習字串型別的方法。例如,下面就是一個可以添加到公共部份 .learn_fromstring() 中的方法。
// Method to learn word relations from a given string
void learn_fromstring(const std::string &sentence)
{
std::istringstream iss(sentence);
std::vector<std::string> tokens{ std::istream_iterator<std::string>{iss},
std::istream_iterator<std::string>{} };
for (size_t i = 0; i < tokens.size() - 1; ++i) {
wordRel[tokens[i]].push_back(tokens[i + 1]);
}
}
在上述方法中,我們先將句子轉換為 istringstream,然後從這個 stream 建立一個單詞(token)向量。然後我們處理每個單詞,並將下一個單詞推到其對映的順序中。例如,如果我們訓練「I am」、「I was」、「I have」這類句子,它會把「I」對映和「am」、「was」、「have」添加到這個向量中。換句話說,它儲存了「I」後面可能出現的下一個單詞。實際上,這些關系是透過單詞索引、權重、啟用函式等建立起來的。例如,「am」通常與「I」搭配使用,因此它們之間的關系更密切,權重系數也應該更高。舉一個簡單的例子,我們先不考慮權重和啟用函式。
現在,我們需要一個公共部份(public p)下的句子生成器,它可以透過考慮單詞之間的關系來生成隨機文本。首先,讓我們舉例說明生成模型,然後再進行解釋。
// Method to generate a sequence of words based on learned relations
std::string sentence_generator(const std::string &startWord, int length)
{
std::string currentWord = startWord;
std::string sequence = currentWord;
for (int i = 0; i < length - 1; ++i)
{
if (wordRel.find(currentWord) == wordRel.end()) break;
std::vector<std::string> nextWords = wordRel[currentWord];
std::uniform_int_distribution<int> distribution(0, nextWords.size() - 1);
currentWord = nextWords[distribution(generator)];
sequence += " " + currentWord;
}
return sequence;
}
在上面的 sentence_generator() 方法中,我們先定義第一個單詞(你可以選擇將第一個使用的單詞儲存在一個倉庫中,也可以隨機選擇)以及要生成的句子長度。然後,我們在迴圈中生成句子的中間單詞。最後,它將返回新生成的序列句子。
就是這樣,非常簡單!
為了理解這個對映內部發生了什麽,我們可以建立另一個方法來揭示單詞之間的關系,如下所示。
// print the word releations
void print_word_relations()
{
std::cout << "Word Relations:" << std::endl;
for (const auto &pair : wordRel)
{
std::cout << pair.first << ":";
for (const auto &word : pair.second)
{
std::cout << " " << word;
}
std::cout << std::endl;
}
std::cout << std::endl;
}
現在我們可以開發主函式了。從這個類中建立一個新的生成式 AI 物件,用 learn_fromstring() 方法訓練一些句子。根據給定的句子,輸出訓練後的單詞關系,我們就可以建立許多新句子了,還可以在每個迴圈中用 sentence_generator() 方法建立一個新的字串。下面是我訓練了一些句子並生成 10 個新句子作為輸出的過程。
int main()
{
GenerativeAI generator;
// Learn from sentences
generator.learn_fromstring("I am generative AI test example");
generator.learn_fromstring("I was a code");
generator.learn_fromstring("I can develop applications in C++");
generator.learn_fromstring("I have a generative code example");
generator.learn_fromstring("I should generate different sentences");
generator.learn_fromstring("I am easy with LearnCPlusPlus.org");
// Print word releations that learnt
generator.print_word_relations();
// Generate new sentences
for (int i = 0; i < 10; ++i)
{
std::cout << "Generated Sentence " << i + 1 << ": " << generator.sentence_generator( "I", 4+rnd()%2 ) << std::endl;
}
system("pause");
return 0;
}
有沒有用 C++ 編寫的簡單生成式 AI 模型的完整範例?
有的,下面就是一個用 C++ 寫的生成式 AI 的完整範例。
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <sstream>
#include <iterator>
#include <algorithm>
#include <random>
std::random_device rnd;
std::mt19937 generator(rnd());
class GenerativeAI
{
private:
std::map<std::string, std::vector<std::string>> wordRel; // map to world releation
public:
// Method to learn word relations from a given string
void learn_fromstring(const std::string &sentence)
{
std::istringstream iss(sentence);
std::vector<std::string> tokens{ std::istream_iterator<std::string>{iss},
std::istream_iterator<std::string>{} };
for (size_t i = 0; i < tokens.size() - 1; ++i) {
wordRel[tokens[i]].push_back(tokens[i + 1]);
}
}
// Method to generate a sequence of words based on learned relations
std::string sentence_generator(const std::string &startWord, int length)
{
std::string currentWord = startWord;
std::string sequence = currentWord;
for (int i = 0; i < length - 1; ++i)
{
if (wordRel.find(currentWord) == wordRel.end()) break;
std::vector<std::string> nextWords = wordRel[currentWord];
std::uniform_int_distribution<int> distribution(0, nextWords.size() - 1);
currentWord = nextWords[distribution(generator)];
sequence += " " + currentWord;
}
return sequence;
}
// print the word releations
void print_word_relations()
{
std::cout << "Word Relations:" << std::endl;
for (const auto &pair : wordRel)
{
std::cout << pair.first << ":";
for (const auto &word : pair.second)
{
std::cout << " " << word;
}
std::cout << std::endl;
}
std::cout << std::endl;
}
};
int main()
{
GenerativeAI generator;
// Learn from sentences
generator.learn_fromstring("I am generative AI test example");
generator.learn_fromstring("I was a code");
generator.learn_fromstring("I can develop applications in C++");
generator.learn_fromstring("I have a generative code example");
generator.learn_fromstring("I should generate different sentences");
generator.learn_fromstring("I am easy with LearnCPlusPlus.org");
// Print word releations that learnt
generator.print_word_relations();
// Generate new sentences
for (int i = 0; i < 10; ++i)
{
std::cout << "Generated Sentence " << i + 1 << ": " << generator.sentence_generator( "I", 4+rnd()%2 ) << std::endl;
}
system("pause");
return 0;
}
結果如下:
最後需要說明一點:為了盡可能讓大家易於理解和便於編碼,我試著制作了大約 20 個不同的範例(包括一些來自 Copilot 的支持)並盡量將其簡化,所以這應該是最簡單易行的生成式 AI 模型了。
推薦閱讀: