首页 > 其他分享 >从零开始学机器学习——构建一个推荐web应用

从零开始学机器学习——构建一个推荐web应用

时间:2024-10-17 09:23:10浏览次数:1  
标签:Web web ONNX 模型 380 从零开始 构建 model 学习

首先给大家介绍一个很好用的学习地址:https://cloudstudio.net/columns

今天,我们终于将分类器这一章节学习完活了,和回归一样,最后一章节用来构建web应用程序,我们会回顾之前所学的知识点,并新增一个web应用用来让模型和用户交互。所以今天的主题是美食推荐。

美食推荐 Web 应用程序

首先,请不要担心,本章节并不会涉及过多的前端知识点。我们此次的学习重点在于机器学习本身,因此我们的目标是将模型打包,使得前端用户能够与模型进行直接的界面交互,而不再依赖于后端输入的形式。

在前面的回归章节中,我们学习了如何使用第三方依赖包 pickle 来创建一个后台生成的 .pkl 后缀的模型文件,并通过 Flask 框架加载该模型,从而在后台暴露接口供调用和分析。今天,我们将探索一个新的知识点——ONNX Web,这将进一步拓宽我们在机器学习模型部署与应用方面的视野。

ONNX Web

ONNX Web 是一个用于在浏览器中运行 ONNX 模型的工具和库,主要用于深度学习模型的推理。ONNX(Open Neural Network Exchange)是一个开放的深度学习模型交换格式,它允许不同深度学习框架之间共享模型。ONNX Web 使得开发者可以将 ONNX 模型直接在网页上运行,通常用于机器学习和深度学习的前端应用。

开发步骤

  • 准备 ONNX 模型:首先,需要一个经过训练并导出的 ONNX 模型。
  • 引入 ONNX Web 库:在你的前端项目中引入 ONNX Web 的 JavaScript 库。可以通过 npm 安装或直接在 HTML 中使用 CDN。
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ort.min.js"></script> 
  • 加载模型:使用 ONNX Web API 加载模型并进行推理。
const session = await ort.InferenceSession.create('./model.onnx');
  • 进行推理:准备输入数据,并使用加载的模型进行推理。
  • 处理输出:根据模型的输出格式处理结果,并在应用中展示。

好的,经过对开发步骤的全面了解后,接下来让我们开始逐步构建一个功能齐全的 Web 应用程序。

构建模型

首先,我们将使用之前清洗后的菜品数据集来训练一个分类模型。

import pandas as pd 
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
from sklearn.metrics import accuracy_score,precision_score,confusion_matrix,classification_report

data = pd.read_csv('../data/cleaned_cuisines.csv')
X = data.iloc[:,2:]
y = data[['cuisine']]
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3)
model = SVC(kernel='linear', C=10, probability=True,random_state=0)
model.fit(X_train,y_train.values.ravel())
y_pred = model.predict(X_test)
print(classification_report(y_test,y_pred))

关于上述这段代码流程,大家可能已经对其有了一定的了解,因此我将不再进行单独的讲解。

运行结果如下所示:模型的精度表现相对令人满意,达到了一个不错的水平。

              precision    recall  f1-score   support

     chinese       0.71      0.72      0.72       238
      indian       0.90      0.86      0.88       259
    japanese       0.76      0.75      0.75       248
      korean       0.83      0.78      0.80       233
        thai       0.73      0.82      0.77       221

    accuracy                           0.79      1199
   macro avg       0.79      0.79      0.78      1199
weighted avg       0.79      0.79      0.79      1199

模型转换到 Onnx

由于使用到了第三方依赖库,我们需要安装一下,命令如下:

! pip install skl2onnx

from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType

initial_type = [('float_input', FloatTensorType([None, 380]))]
options = {id(model): {'nocl': True, 'zipmap': False}}
onx = convert_sklearn(model, initial_types=initial_type, options=options)
with open("./model.onnx", "wb") as f:
    f.write(onx.SerializeToString())

这段代码的整体目的是准备将一个 Scikit-Learn 模型转换为 ONNX 格式的过程,定义了输入数据的结构以及转换时的一些配置选项。

  • initial_type 是一个列表,定义了模型的输入特征及其数据类型。
  • 'float_input' 是输入的名称,可以是任意字符串,用于标识输入。
  • FloatTensorType([None, 380]) 指定输入数据的形状。这里的 [None, 380] 表示:
    • 第一个维度是 None,表示可以接受任意数量的样本(即批处理大小)。
    • 第二个维度是 380,表示每个样本有 380 个特征。
  • options 是一个字典,用于指定转换过程中的一些选项。
    • id(model) 获取模型的唯一标识符(ID),用作字典的键。
    • 选项中:
      • 'nocl': True 表示在转换时不使用类别标签的映射(Class Label Mapping)。
      • 'zipmap': False 表示在输出的 ONNX 模型中不使用 ZipMap 功能,这意味着输出将是一个多维数组,而不是一个字典结构。通常在处理分类问题时,ZipMap 可能会将类别标签转换为字典形式,但这里选择保持原始输出。

最后一步则是将模型写入文件即可。

可视化模型工具——Netron

Netron 是一个用于可视化和分析深度学习模型的开源工具,支持多种模型格式,包括 ONNX、TensorFlow、Keras、PyTorch 等。它提供了一个直观的图形界面,帮助用户理解和检查模型结构、层、参数等信息。

开源地址:https://github.com/lutzroeder/Netron?tab=readme-ov-file

其中包含了多种系统的安装版本,方便用户根据自己的需求进行选择和安装。此外,它还提供了在线Web应用,用户可以直接通过浏览器访问,无需额外安装任何软件。

在线Web应用地址如下:https://netron.app/

image

在我们将刚才训练好的模型上传后,可以清晰地查看模型的详细信息。

image

同样,你可以通过点击每一个框框来进一步探索模型的具体信息。例如,如果我们点击了“SVMClassifier”这一选项,屏幕上将会弹出一个详细的对话框,如下所示。

image

好的,以后如果你想查看模型的具体信息和性能表现,当然可以利用这个可视化工具作为参考。

Web 应用程序

这次,我们将不再使用Python后台来启动应用,而是完全依赖一个前端静态页面来实现所有功能。

<!DOCTYPE html>
<html>
    <header>
        <title>Cuisine Matcher</title>
    </header>
    <body>
        <h1>Check your refrigerator. What can you create?</h1>
        <div id="wrapper">
            <div class="boxCont">
                <input type="checkbox" value="4" class="checkbox">
                <label>apple</label>
            </div>
        
            <div class="boxCont">
                <input type="checkbox" value="247" class="checkbox">
                <label>pear</label>
            </div>
        
            <div class="boxCont">
                <input type="checkbox" value="77" class="checkbox">
                <label>cherry</label>
            </div>

            <div class="boxCont">
                <input type="checkbox" value="126" class="checkbox">
                <label>fenugreek</label>
            </div>

            <div class="boxCont">
                <input type="checkbox" value="302" class="checkbox">
                <label>sake</label>
            </div>

            <div class="boxCont">
                <input type="checkbox" value="327" class="checkbox">
                <label>soy sauce</label>
            </div>

            <div class="boxCont">
                <input type="checkbox" value="112" class="checkbox">
                <label>cumin</label>
            </div>
        </div>
        <div style="padding-top:10px">
            <button onClick="startInference()">What kind of cuisine can you make?</button>
        </div>      
        <!-- import ONNXRuntime Web from CDN -->
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ort.min.js"></script>
        <script>
        const ingredients = Array(380).fill(0);
        
        const checks = [...document.querySelectorAll('.checkbox')];
        
        checks.forEach(check => {
            check.addEventListener('change', function() {
                // toggle the state of the ingredient
                // based on the checkbox's value (1 or 0)
                ingredients[check.value] = check.checked ? 1 : 0;
            });
        });

        function testCheckboxes() {
            // validate if at least one checkbox is checked
            return checks.some(check => check.checked);
        }

        async function startInference() {

            let atLeastOneChecked = testCheckboxes()

            if (!atLeastOneChecked) {
                alert('Please select at least one ingredient.');
                return;
            }
            try {
                // create a new session and load the model.
                
                const session = await ort.InferenceSession.create('./model.onnx');

                const input = new ort.Tensor(new Float32Array(ingredients), [1, 380]);
                const feeds = { float_input: input };

                // feed inputs and run
                const results = await session.run(feeds);

                // read from results
                alert('You can enjoy ' + results.label.data[0] + ' cuisine today!')

            } catch (e) {
                console.log(`failed to inference ONNX model`);
                console.error(e);
            }
        }
               
    </script>
    </body>
</html>

大致解释下js部分的代码:

  • 创建一个长度为 380 的数组 ingredients,初始值为 0,用于表示选择的食材状态。
  • 获取所有的复选框,并为每个复选框添加 change 事件监听器。当复选框状态变化时,根据复选框的 value 更新 ingredients 数组,选中为 1,未选中为 0。
  • testCheckboxes 函数用于检查是否至少选中一个复选框。
  • startInference 函数首先检查是否选中至少一个食材。如果没有,则弹出提示框。
    • 如果有选中食材,异步加载 ONNX 模型 (model.onnx)。
    • 创建一个张量 input,形状为 [1, 380],用以存储食材信息。
    • 调用模型的 run 方法进行推理,并获取结果。
    • 结果中的 label 数据用于显示推荐的菜肴。

我们来运行一下,这里用到了http-server依赖:

npm install --global http-server

运行后,如图所示:

image

至此,我们已经完成了整个Web应用程序的构建过程。

总结

在这次学习旅程中,我们成功构建了一个美食推荐的Web应用程序,探索了机器学习和Web开发的交集。通过使用ONNX Web,我们能够将训练好的模型直接集成到浏览器中,让用户可以与模型进行互动,而无需依赖后端,这极大地提高了用户体验。结合Netron这一强大的可视化工具,我们不仅能够分析和理解模型的内部结构,还可以直观地展示模型的性能与特点。

至此,我们的分类章节圆满结束,感谢大家的认真学习和参与。在下一次的课程中,我们将深入探讨聚类技术,了解其在数据分析和机器学习中的重要应用。


我是努力的小雨,一名 Java 服务端码农,潜心研究着 AI 技术的奥秘。我热爱技术交流与分享,对开源社区充满热情。同时也是一位腾讯云创作之星、阿里云专家博主、华为云云享专家、掘金优秀作者。

标签:Web,web,ONNX,模型,380,从零开始,构建,model,学习
From: https://www.cnblogs.com/guoxiaoyu/p/18447175

相关文章

  • 从零开始学习c语言,并逐步成计算机语言工程师的想法与实践。(1)学习思路分享
        在接下来的分享过程中,我将分享我的学习思路,并将实践过程分享出来。    首先,整体上计算机基础知识不能缺少,因此需要学习计算机基础。要想开发软件,编程语言必不可少,此处我选择从c语言入手。与计算机基础并行学习。在此期间通过“多邻国”手机app学习英语,通......
  • Neo4j 构建文本类型的知识图谱
    Neo4j是一个强大的图数据库,用于构建和查询各种类型的图数据结构。构建知识图谱是一项常见任务,尤其在处理自然语言处理(NLP)和文本信息时。基于Neo4j,可以将文本数据转换为知识图谱,使得复杂的文本关系以图结构存储,并且能够高效查询。构建文本类型知识图谱的基本过程定义......
  • Next.js 零基础开发入门教程2 构建基础脚手架 2024最新更新中|曲速引擎 Warp Drive
    开发目标我们将构建一个简化版本的财务仪表板,其内容包括:公共主页、登录页面、受身份验证保护的仪表板页面、用户可以添加、编辑和删除发票这篇文章先创建一个简单的nextjs脚手架页面安装pnpm包管理器接上一篇,开发环境都准备好之后,我们来做创建项目的准备,首先先判断上一篇的环......
  • 作物与杂草的智能识别,基于YOLOv8全系列参数模型【n/s/m/lx/】开发构建田间低头作物杂
    一、背景田间杂草的有效管理是现代农业生产中面临的重要挑战之一。杂草不仅竞争作物的养分、水分和阳光,还可能成为害虫和病原体的寄主,从而降低农作物的产量和品质。因此,开发高效、精确的杂草检测和管理系统对于提高农业生产效率、降低化学除草剂的使用以及保护环境具有重要......
  • 变量与数据类型:程序的基本构建块!
    Java入门之旅:变量与数据类型的奥秘在编程的世界里,变量就像是每个程序员的好伙伴,它们在代码中存储着各种信息,帮助我们在计算机中执行复杂的逻辑。而数据类型则是对这些变量的基本属性定义,影响着它们的行为和存储方式。今天,就让我们一起探索Java中的变量和数据类型,揭开它们的......
  • 【CTF-SHOW】Web入门 Web27-身份证日期爆破 【关于bp intruder使用--详记录】
    1.点进去是一个登录系统,有录取名单和学籍信息发现通过姓名和身份证号可以进行录取查询,推测录取查询可能得到学生对应学号和密码,但是身份证号中的出生日期部分未知,所以可以进行爆破2.打开bp抓包这里注意抓的是学院录取查询系统发送POST类型进行查询的包,第一遍抓不到很正......
  • 27K star!有没有显卡都能搞,Langchain-Chatchat 快速基于LLM构建本地智能知识库
    觉得搞一个AI的智能问答知识库很难吗?那是你没有找对方向和工具,今天我们分享一个开源项目,帮助你快速构建基于Langchain和LLM的本地知识库问答,在GitHub已经获得27Kstar,它就是:Langchain-Chatchat......
  • 探索 Python Web 开发:从框架到爬虫
    Python是Web开发中广泛使用的编程语言,因其简单、灵活和强大的生态系统,适合构建各种类型的Web应用和API。在本篇博客中,我们将讨论Web开发的几个重要主题,包括Flask和Django框架、API开发、HTTP请求处理以及网页爬虫的基础。9.1Flask框架基础Flask是一个轻量级......
  • 外网爆火!仅需Python基础,即可从0构建LLM大语言模型(附PDF)
    在当今人工智能技术飞速发展的时代,大型语言模型(LLM)作为聊天机器人、文本生成和理解等应用的核心,已经成为研究和商业领域关注的焦点。但对于大多数开发者来说,它们的工作原理仍然是一个黑箱,更不用说如何从头开始构建一个这样的模型了。而《从头开始构建大型语言模型》这本书,......
  • C++构建工具-构建系统
    构建CI/CDCI这步,首先需要一个版本控制系统,当前最好用的就是git流程:主线分支上设置静态代码检查,用来检测每一笔提交的质量,比如命名规范等。 还会设置自动化单元测试,看守代码功能,并进行代码覆盖率分析代码拉取功能; 构建 安装包依赖项功能,依赖项需......