当前位置:首页 > 技术 > 正文内容

在openEuler系统中构建AI图像识别应用的完整实践指南

访客 技术 2026年7月8日 1

1. 研究背景与技术选型

深度学习技术在计算机视觉领域广泛应用,图像分类作为核心任务之一,在多个行业发挥重要作用。openEuler作为开源服务器操作系统,为AI应用提供了稳定可靠的运行环境。

1.1 服务器硬件规格

实验采用高性能计算服务器,配置如下:

  • CPU: Intel Xeon Gold 6248R (24核48线程)
  • 内存: 256 GB DDR4 ECC
  • GPU: 1 x NVIDIA RTX A6000
  • 显存: 48 GB GDDR6
  • 存储: 2 TB NVMe SSD

1.2 系统环境与部署方案

选用openEuler 22.03 LTS SP3版本,该版本具有长期支持特性。为确保环境隔离性,采用容器化部署方式,使用Docker引擎管理AI开发环境。

1.3 框架与模型选择

选择PyTorch 2.1.2作为深度学习框架,采用ResNet-50架构进行迁移学习。使用CIFAR-10数据集进行模型训练和验证,该数据集包含10个类别的60000张32x32彩色图像。

2. AI开发环境配置

2.1 系统状态检查

通过以下命令确认系统基本信息:

cat /etc/os-release
uname -r
lscpu
nvidia-smi

2.2 Docker安装配置

执行以下命令安装并启动Docker服务:

yum update -y
yum install -y yum-utils
yum-config-manager --add-repo https://repo.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.io
systemctl start docker
systemctl enable docker

2.3 获取AI运行时镜像

从镜像仓库拉取包含PyTorch和CUDA环境的基础镜像:

docker pull openeuler/openeuler_ai:latest

2.4 创建开发容器

启动容器实例,挂载工作目录并分配GPU资源:

docker run -it --gpus all -v $(pwd):/workspace openeuler/openeuler_ai:latest

3. 图像分类模型实现

3.1 模型训练脚本

创建训练程序classify_images.py:

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
from torchvision.models import resnet50, ResNet50_Weights
from tqdm import tqdm
import time

def execute_training():
    # 设备检测
    compute_device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    print(f"运行设备: {compute_device}")

    # 数据预处理
    print("准备数据集...")
    train_transform = transforms.Compose([
        transforms.Resize(256),
        transforms.RandomCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    ])

    test_transform = transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    ])

    # 数据加载
    training_data = torchvision.datasets.CIFAR10(root='./dataset', train=True, download=True, transform=train_transform)
    training_loader = torch.utils.data.DataLoader(training_data, batch_size=64, shuffle=True, num_workers=4)

    validation_data = torchvision.datasets.CIFAR10(root='./dataset', train=False, download=True, transform=test_transform)
    validation_loader = torch.utils.data.DataLoader(validation_data, batch_size=64, shuffle=False, num_workers=4)

    categories = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
    print("数据集准备完成.")

    # 模型初始化
    print("加载预训练模型...")
    network = resnet50(weights=ResNet50_Weights.IMAGENET1K_V2)
    features_count = network.fc.in_features
    network.fc = nn.Linear(features_count, 10)
    network = network.to(compute_device)
    print("模型加载完成.")

    # 损失函数与优化器
    loss_function = nn.CrossEntropyLoss()
    optimizer_algorithm = optim.Adam(network.parameters(), lr=0.001)

    # 训练循环
    training_epochs = 5
    print(f"开始训练 {training_epochs} 轮...")
    start_timestamp = time.time()

    for current_epoch in range(training_epochs):
        network.train()
        accumulated_loss = 0.0
        progress_bar = tqdm(training_loader, desc=f"第 {current_epoch+1}/{training_epochs} 轮 [训练中]")
        for batch_index, batch_data in enumerate(progress_bar):
            input_data, target_labels = batch_data[0].to(compute_device), batch_data[1].to(compute_device)
            optimizer_algorithm.zero_grad()
            prediction_outputs = network(input_data)
            loss_value = loss_function(prediction_outputs, target_labels)
            loss_value.backward()
            optimizer_algorithm.step()
            accumulated_loss += loss_value.item()
            progress_bar.set_postfix({'损失': accumulated_loss / (batch_index + 1)})

        # 验证阶段
        network.eval()
        correct_predictions = 0
        total_samples = 0
        with torch.no_grad():
            validation_progress = tqdm(validation_loader, desc=f"第 {current_epoch+1}/{training_epochs} 轮 [验证中]")
            for validation_batch in validation_progress:
                sample_images, sample_labels = validation_batch[0].to(compute_device), validation_batch[1].to(compute_device)
                output_predictions = network(sample_images)
                _, predicted_classes = torch.max(output_predictions.data, 1)
                total_samples += sample_labels.size(0)
                correct_predictions += (predicted_classes == sample_labels).sum().item()
        
        accuracy_percentage = 100 * correct_predictions / total_samples
        print(f"第 {current_epoch+1}/{training_epochs} 轮 - 验证准确率: {accuracy_percentage:.2f}%")

    end_timestamp = time.time()
    print(f"训练完成. 总耗时: {end_timestamp - start_timestamp:.2f} 秒")

    # 模型保存
    torch.save(network.state_dict(), 'trained_model.pth')
    print("模型已保存至 trained_model.pth")

if __name__ == '__main__':
    execute_training()

3.2 执行模型训练

在容器环境中运行训练脚本:

python classify_images.py

3.3 模型推理实现

创建推理程序predict_image.py:

import torch
import torchvision.transforms as transforms
from torchvision.models import resnet50
from PIL import Image
import argparse

def perform_inference(image_file_path):
    # 设备配置
    execution_device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

    # 模型加载
    model_instance = resnet50()
    feature_dimensions = model_instance.fc.in_features
    model_instance.fc = torch.nn.Linear(feature_dimensions, 10)
    model_instance.load_state_dict(torch.load('trained_model.pth'))
    model_instance = model_instance.to(execution_device)
    model_instance.eval()

    # 类别定义
    category_names = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

    # 图像预处理
    preprocessing_pipeline = transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    ])

    # 图像处理
    input_image = Image.open(image_file_path).convert('RGB')
    processed_tensor = preprocessing_pipeline(input_image).unsqueeze(0).to(execution_device)

    # 推理执行
    with torch.no_grad():
        model_outputs = model_instance(processed_tensor)
        _, predicted_class = torch.max(model_outputs, 1)

    # 结果输出
    print(f"图像文件: '{image_file_path}'")
    print(f"预测类别: '{category_names[predicted_class.item()]}'")

if __name__ == '__main__':
    argument_parser = argparse.ArgumentParser(description='CIFAR-10图像分类推理')
    argument_parser.add_argument('--image', type=str, required=True, help='待识别图像路径')
    parsed_arguments = argument_parser.parse_args()
    perform_inference(parsed_arguments.image)

3.4 执行推理测试

使用训练好的模型进行图像识别:

python predict_image.py --image sample_image.png

4. 实验总结

本次实践验证了在openEuler系统上构建AI图像分类应用的可行性。通过容器化部署方案,成功实现了从环境配置到模型部署的完整流程。实验结果显示,该技术方案能够有效支持AI应用开发需求。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。