當前位置: 妍妍網 > 碼農

不到 100 行程式碼,用 C++ 建立生成式 AI 模型?

2024-05-17碼農

近年來 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 模型了。

推薦閱讀: