面向 Web 开发人员的机器学习

作为一个 90% 的时间都从事网络相关项目的人,数据科学和机器学习并不是我职业生涯中大部分时间的核心竞争力或兴趣领域。

在过去的两年里,机器学习已经成为我作为开发人员的工具箱中的一个重要组成部分。

最初,前景一片混乱!我们使用了 Keras、PyTorch、Tensorflow 和许多其他工具。幸运的是,自从 ChatGPT 和 Sentence Transformers 出现以来,构建与 AI 相关的产品现在比以往任何时候都更容易。

如果您需要在项目中添加一点 AI 魔法,那么您可能只需对 OpenAI 端点进行简单的 rest 调用即可,但是,如果您正在构建更复杂的产品,并且对深度机器学习概念(例如 RAG、Langchain 等)几乎没有经验,那么本文将是您的理想入门读物。

🤦🏾 我们实际上滥用了“AI”一词。机器学习只是 AI 的一个子集。尽管如此,为了简单起见,因为现在每个人都在追随“AI”的潮流。我将交替使用这些术语。抱歉!

模型:放弃控制

机器学习中没有或很少有“IF”、“THEN”、“ELSE”或“DO WHILE”控制,因此机器学习与传统编程相比是一种不同的范式。

您通常会使用自然语言和配置式编程来调整模型,使其朝着您希望的方向发展。但归根结底,您永远无法 100% 控制模型的运行。在大多数情况下,您可以非常确定地预测结果,但这与编程不同,在编程中,我们编写规则和控制流来精确引导用户沿着我们希望的路径前进。

模型在很大程度上是神经网络的“黑匣子”。你可以将神经网络视为一串微小节点(神经元)。神经网络中的所有节点共同构建了一些模式识别能力,模型利用这些能力来分析用户的输入并生成适当的响应。

models are blackboxes

神经网络通常包含 3 种类型的层:

  • 输入层:接收整体数据。此层中的神经元将表示输入数据的各种特征。例如,对于“猫”的图像,一些神经元将表示毛皮,其他神经元表示尾巴,其他神经元表示胡须,等等。
  • 隐藏层:这些层进一步分析从第一层提取的特征,以确定权重和偏差。本质上,数学算法应用于数据,以确定发展模型推理和预测能力的模式。
  • 输出层:该层现在使用来自上一层的“学习”来构建对用户的适当响应。在猫图像示例中,我们可能想要对动物类型进行分类。然后,该层将返回“猫”。
  • 训练模型时,您会在多次迭代中将相同的数据传递给模型。所有层的一个完整数据循环称为一个“epoch”。每次循环一个 epoch 时,模型都会不断调整和优化其模式识别能力(太多 epoch 可能会带来不利影响,请阅读更多有关“模型损失函数”的内容)。

    通过 epoch 进行训练对于提高模型的准确性至关重要。例如:如果第一张图片是“斯芬克斯”猫科动物,神经网络还不知道其他猫科动物,因此会根据这种猫科动物对猫科动物做出各种假设。

    这会导致奇怪的预测,因为“斯芬克斯猫”与普通家猫有显著不同。在第二个时期,网络现在了解了其他 99 种猫科动物,因此对不同物种及其特征有了整体了解。每个后续时期都会重新分析数据并寻找优化模型准确性的方法。

    通常在训练模型时,您还会提供一个具有准确示例的小样本数据集,以便模型可以在训练阶段使用该数据集来帮助微调其准确性。

    构建模型的工具和框架

    在 Python 世界中,PyTorch 是构建机器学习模型方面无可争议的领导者。它是开源且免费提供的,因此几乎任何人都可以从头开始实现自己的模型,或扩展其他人的模型。

    Machine learning tools

    在构建模型之前,您需要某种数据集。通常是 CSV 或 JSON 文件。您可以使用自己的数据从头构建自己的数据集,从某处抓取数据,或者使用 Kaggle。

    💡 Kaggle 是一个“机器学习者”社区,您可以在其中找到各种免费提供的数据集,甚至可用于商业和非商业目的的模型。

    在常规 Python 列表或字典中处理大型数据集可能会变得效率低下,因此除了 Pytorch 之外,您还需要学习 2 个有助于解析和处理数据的库(以及用于 LLM 特定任务的 Langchain):

  • Pandas:这将允许您加载和解析 CSV/JSON 训练数据,并将其有效地格式化为 PyTorch 模型需要的数据格式。此外,Pandas 具有一致的 API,因此您可以轻松地在数据源之间切换,而无需在脚本中进行重大重构。
  • Numpy:模型通常使用文本的向量嵌入(数字表示),即浮点数数组。模型在整个过程中使用 Numpy 执行各种数值计算。Pytorch 模型通常会以 Numpy 数组的形式返回结果,因此您需要相应地处理或转换该结果。
  • Langchain:一个功能强大的 LLM 实用程序库,可让您更轻松地使用 LLM API 和模型。您当然可以将 REST API 或 Python 库用于您的 LLM,并且无需 Langchain 即可顺利使用它。对于较大的应用程序,Langchain 简化了常见任务,例如构建系统提示、代理、RAG 检索器等。
  • 各种预先训练的模型

    您可能知道 Llama3 和 OpenAI 模型,但在机器学习领域,有数百甚至数千种模型可用于各种机器学习任务。甚至 OpenAI 本身也有几个不同的模型:GPT3.5 (gpt3.5-turbo...)(支持 ChatGPT 免费版)、GPT-4(支持 ChatGPT pro)、Whisper(用于音频转文本)、DALLE(图像生成)等等。

    wide variety

    一些最受欢迎的模型类型包括:

  • 文本嵌入:将文本转换为矢量嵌入。有一个排行榜可以对此类模型进行排名:https://huggingface.co/spaces/mteb/leaderboard
  • 图像生成:DALLE 3、Midjourney、Stable Diffusion 等。
  • 文本分类:可以对各种数据进行分类的模型,例如垃圾邮件分类、产品分类、标记等...一些模型示例:FastText、BERT、facebook/bart-large-mnli
  • 图像分类:给定一张图像,这些模型可以确定合适的标签、标记或说明。示例:microsoft/resnet-50、OpenAI CLIP。
  • 对象检测:给定一张图像,检测图像中的各种实体。示例:facebook/detr-resnet-50、keremberke/yolov5m-garbage
  • 文本到语音(反之亦然):microsoft/speecht5_tts、OpenAI Whisper、OpenAI TTS。
  • 大型语言模型:可以执行上述部分或全部任务的通用模型。示例:Chat GPT 3.5、Mixtral、LLama3、Gemini。
  • 与我之前提到的“Kaggle”类似,当谈到模型时,寻找预先训练模型的最佳地点之一就是 HuggingFace。

    除了提供模型之外,他们还提供了一个名为“sentence-transformers”的开源库,让您能够以一致的方式轻松地在代码中使用他们的模型。

    这是一个使用 Huggingface“句子转换器”库生成向量嵌入的简单示例:

    from sentence_transformers import SentenceTransformer
    sentences = ["Some sentence or phrase here"]
    # Notice we pass in the model name:# 'sentence-transformers/all-mpnet-base-v2'
    # You can easily swap this model out for any other
    # - compatible model e.g. "sentence-transformers/all-MiniLM-L6-v2"
    
    model = SentenceTransformer('sentence-transformers/all-mpnet-base-v2')
    
    # Will convert the sentences into vector embeddings.
    embeddings = model.encode(sentences)
    
    # Will print a Numpy array
    print(embeddings)

    什么是向量嵌入?

    我已经多次提到过这个概念,只是为了向那些不熟悉的人澄清一下。

    机器学习的本质是统计算法,它们使用大量数学公式来生成预测并执行其他机器学习任务。

    现在您可以想象,文本和字母本质上不是数学。您无法对它们进行计算,因此,为了使数学算法有效工作,我们需要将单词/字母转换为数字。

    然后将每个短语或单词转换为浮点数字数组(向量),并将多个向量组合在一起(例如句子或段落)以形成向量嵌入。

    向量嵌入根据单词之间的距离、单词在相似句子中出现的频率等来捕获上下文信息。这可以为 COISINE 相似度、ANN 和 KNN 等算法存储足够的信息,以计算文本的语义含义。

    你可以想象,向量嵌入最有用的用例之一是执行语义搜索。通过语义搜索,即使搜索词未出现在结果中,算法也可以识别句子和单词(这与 SOLR 或 Elasticsearch 不同,后者只查找同义词或拼写模糊的关键字)。

    您可以按如下方式生成向量嵌入:

    from sentence_transformers import SentenceTransformer
    model = SentenceTransformer('sentence-transformers/all-mpnet-base-v2')
    embeddings = model.encode(["Machine learning"])
    print(embeddings)

    结果将是一个 Numpy 数组(实际的向量嵌入要大得多,我在下面将其缩短以仅给出一个例子):

    [[
    -2.14947201e-02 6.24050908e-02 -6.70606121e-02 1.17204664e-02 
    -2.23315824e-02 3.22391130e-02 -1.10149011e-02 2.08304841e-02 
    -9.21188202e-03 3.96048091e-02 1.33278236e-01 4.91726398e-02 
    -2.97797378e-02 6.26323521e-02 2.64899582e-02 -8.43470395e-02 
    8.12786724e-03 7.97691289e-03 -5.54570891e-02 6.59016613e-03 
    1.62357709e-03 7.52743008e-03 2.48725782e-03 4.35999036e-03
    ]]

    根据您使用的模型,维度会有所不同(浮点数)。在本例中,模型生成“768”个浮点数。这并不总是正确的,但在大多数情况下,维度越大,准确率越高。

    什么是检索增强生成 (RAG)?

    这将是您需要为 Web 应用程序构建的最常见的机器学习系统之一。

    当你向 ChatGPT 提问时,它会参考其庞大的数据数据集并根据该上下文生成数据。有时它会产生幻觉并给你错误的信息。

    其他时候,它可能会给你正确的信息,但在你独特的环境下,这些信息可能不相关或太宽泛而无用。例如:“Macbook Pro 的价格是多少?”,模型会回答“从 1,299 美元起……”。

    这可能是正确的,但它不是很有用,因为它没有给我当地货币的价格,或者提供有关每种型号的更多详细信息。

    RAG 系统旨在解决这个问题;本质上,你给模型一个自定义数据集,然后它将其响应范围仅限于你的数据集,从而提高准确性并为您的域/业务提供更好的本地环境。

    这与微调不同。在微调中,您将采用预先训练的模型,并通过为您的用例提供自定义数据集来扩展其功能。然后,您必须对模型重新进行训练,模型将生成新的训练状态,因此模型的上下文将冻结在此状态,而不是实时的。

    使用 RAG 系统,您无需重新训练模型,而是实时提供上下文数据,因此您不需要在每次数据发生变化时都训练模型。

    LLM 使用其原始训练数据作为其开发推理的基础,但它使用 RAG 执行的任何生成或预测任务都将限定在您的自定义数据范围内,并且优先考虑您的数据而不是其原始数据集。

    如果您想了解如何构建 RAG 系统,可以查看我之前在这里写的一篇文章。

    如何申办自己的法学硕士学位?

    当你第一次接触机器学习时,我建议你不要摆弄像 Llama3 这样的开源模型,而是先专注于使用 OpenAI 模型并熟悉它们的 API。

    虽然 OpenAI 积分相当便宜并且可以为您带来良好的效益,但有时,当您构建大型应用程序时,您可能希望运行自己的内部模型。

    您有以下几个开源选项:

  • Llama3——由 Facebook 开发。
  • Mixtral——由一家在机器学习领域掀起波澜的独立公司开发。
  • Phi3 - 由微软开发,非常紧凑且高效。该型号甚至可以在移动设备上运行。
  • 我不会碰谷歌的 Gemma 模型,我最初尝试过它,但效果不佳,不过,公平地说,这是在它推出后的第一周内。

    根据您的 GPU 资源,您可能希望首先尝试 Phi3,然后是 Mixtral,最后是 Llama3。Llama3 应该是性能最佳的型号。它对资源的占用稍微大一些,您可能并不总是需要这种能力。

    要运行模型,您可以使用 ollama。我还在此处提供了有关如何设置的教程。

    结论

    希望我已经为您提供了足够的见解,以开始将您的技能扩展到机器学习领域,当然,机器学习近年来经历了许多变化,并且库/模型仍在不断发展。

    我建议不要被所有的炒作所迷惑,而是先选择 Pandas、NumPy 并尝试一下 Huggingface 模型。

    一旦你对这些有了扎实的掌握,就可以继续使用 Langchain 并与 OpenAI 集成来构建一个简单的 RAG,然后构建一个简单的代理。

    快乐建造!