当前位置: 欣欣网 > 码农

不到 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 模型了。

推荐阅读: