0

0

【AI达人特训营】多模型集成学习的艺术作品作者识别

P粉084495128

P粉084495128

发布时间:2025-07-31 10:17:50

|

1048人浏览过

|

来源于php中文网

原创

该项目借助多模型集成学习识别艺术作品作者。使用PaddleClas训练ResNet50_vd、VGG16和PPLCNetV2模型,基于含49位作者、7226张图片的Art数据集,经数据处理后划分训练集和验证集。通过硬投票集成模型结果,可纠正单一模型错误,提升识别效果,如成功识别Edgar Degas和Rembrandt的作品。

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

【ai达人特训营】多模型集成学习的艺术作品作者识别 - php中文网

多模型集成学习的艺术作品作者识别

0 项目背景

AI可以去理解画作,提取关键信息或者使用GAN网络去生成新的画作,于是可以通过训练人工智能去尝试识别艺术作品,识别名画的作者。

比如下图是法国印象派画家Edgar Degas的作品

【AI达人特训营】多模型集成学习的艺术作品作者识别 - php中文网        

接下来我们通过使用PaddleClas来训练人工智能,使其能够认出一些艺术家的作品,也便于我们了解每位艺术家的创造风格。

本项目使用PaddleClas来分别训练ResNet50_vd模型、VGG16模型和PPLCNetV2模型,然后将艺术品图片输入进三个不同模型进行识别,每个模型都会给出一个识别结果,然后将每个模型的识别结果进行集成学习,采用硬投票这种简单的方式进行多模型集成识别。

至于为什么需要使用多模型集成学习?

多模型集成主要为了解决单一模型不够全面的问题,不能保证每一个分类器都能得到正确的答案;使用多模型集成学习,即便某一个分类器得到了错误的预测,其他的分类器也可以将错误纠正回来,本项目采用硬投票只是多模型集成学习的其中一种方式

1 简介

1.1项目如何实现

采用paddleclas进行图像分类任务。 paddleclas官方文档连接如下:

https://gitee.com/paddlepaddle/PaddleClas/blob/release/2.2/docs/zh_CN/tutorials/quick_start_new_user.md

1.2 多模型集成学习

由于单个模型难免会产生误差,为了提高预测效果,如果某一个分类器得到了错误的预测,其他的分类器也可以将错误纠正回来,于是将多个训练模型进行集成学习。采用的集成学习方式是硬投票方式。

2 数据集介绍

Art数据集包含49个作者和7226张艺术品图片,在数据集文件中,name_liat.txt文件是存放作者id和对应的作者名称,而在train.csv文件中则存放着filename和label表示每个作品的文件名和对应的作者id。

友情提示:数据集仅供学习和个人使用

data/Art/
├── name_list.txt├── test
│   ├── 0.jpg│   ├── 1.jpg │   └── ......
├── train
│   ├── 0.jpg├── train.csv├── name_list.txt└── train分布.png
   

3 数据处理

In [1]
# 先导入所需要的库from sklearn.utils import shuffleimport osimport pandas as pdimport numpy as npfrom PIL import Imageimport paddleimport random
   
In [2]
# 忽略(垃圾)警告信息# 在python中运行代码经常会遇到的情况是——代码可以正常运行但是会提示警告,有时特别讨厌。# 那么如何来控制警告输出呢?其实很简单,python通过调用warnings模块中定义的warn()函数来发出警告。我们可以通过警告过滤器进行控制是否发出警告消息。import warnings
warnings.filterwarnings("ignore")
   

3.1 解压数据集

In [3]
!unzip -qo /home/aistudio/data/data151473/Art.zip -d ./data/Art
   

3.2读取数据

数据集由于图片分散在tain文件和test中不是很方便,所以可以根据data/Art/train.csv文件从中读取所有的文件名filename和对应的label,生成所有图片的all_list.txt,其中每一条数据Art/img/0.jpg 0包含图片数据的路径和对应的作者id,中间有个空格,数据集大小一共是7727.

In [4]
import csvimport osdef get_all_txt():
    with open("data/Art/train.csv") as cfile:
        i=0
        reader = csv.DictReader(cfile)
        f = open("all_list.txt", "w")
        all_list = []        for row in reader:
            i=i+1
            all_list.append("Art/img/"+row.get("filename")+".jpg"+" "+row.get("label") + "\n")
        
        allstr = ''.join(all_list)
        f = open('all_list.txt','w',encoding='utf-8')
        f.write(allstr)        return all_list , i
all_list,all_lenth = get_all_txt()print(all_lenth)
       
7227
       

3.3 打乱数据

先把数据打乱,然后按照比例划分数据集

In [5]
# 把数据打乱all_list = shuffle(all_list)
allstr = ''.join(all_list)
f = open('all_list.txt','w',encoding='utf-8')
f.write(allstr)print("打乱成功,并重新写入文本")
       
打乱成功,并重新写入文本
       

3.4划分数据集

我们总共是7227张图片,按照经典的划分方式0.9:0.1

train_list.txt(训练集,6504张图)

val_list.txt(验证集,723张图

In [6]
# 按照比例划分数据集Art的数据有7227张图片,不算大数据,一般9:1即可train_size = int(all_lenth * 0.9)
train_list = all_list[:train_size]
val_list = all_list[train_size:]print(len(train_list))print(len(val_list))
       
6504
723
       

生成train_list.txt和val_list.txt文件

Cutout.Pro
Cutout.Pro

AI驱动的视觉设计平台

下载
In [7]
# 运行cell,生成训练集txt train_txt = ''.join(train_list)
f_train = open('train_list.txt','w',encoding='utf-8')
f_train.write(train_txt)
f_train.close()print("train_list.txt 生成成功!")# 运行cell,生成验证集txtval_txt = ''.join(val_list)
f_val = open('val_list.txt','w',encoding='utf-8')
f_val.write(val_txt)
f_val.close()print("val_list.txt 生成成功!")
       
train_list.txt 生成成功!
val_list.txt 生成成功!
       

4 安装环境

解压我放在work目录下已经修改好的PaddleClas.zip文件

In [8]
!unzip -qo ./work/PaddleClas.zip -d ./PaddleClas/
   
In [ ]
# 更新一下依赖!pip install --upgrade -r PaddleClas/requirements.txt -i https://mirror.baidu.com/pypi/simple
   
In [10]
%cd PaddleClas
!ls
       
/home/aistudio/PaddleClas
dataset     __init__.py  output		ppcls		  result.txt  tools
hubconf.py  MANIFEST.in  paddleclas.py	requirements.txt  setup.py    work
       

5 移动数据集和修改配置文件

5.1 移动数据集

In [11]
!mkdir ../data/Art/img
   
In [12]
!mv ../data/Art/train/* ../data/Art/img
!mv ../data/Art/test/* ../data/Art/img
   
In [13]
# 移动list.txt文件到对应目录!mv ../all_list.txt ../data/Art
!mv ../train_list.txt ../data/Art
!mv ../val_list.txt ../data/Art/
   
In [14]
# 移动标签文件到对应目录!cp ../data/Art/name_list.txt ../data/Art/label_list.txt
   

5.3 移动修改好的配置文件到对应目录

In [15]
!cp ../work/ResNet50_vd.yaml ./ppcls/configs/quick_start/ResNet50_vd.yaml
!cp ../work/VGG16.yaml ./ppcls/configs/ImageNet/VGG/VGG16.yaml
!cp ../work/PPLCNetV2_base.yaml ./ppcls/configs/ImageNet/PPLCNetV2/PPLCNetV2_base.yaml
   

5.4 使用已经训练好的权重(可选)

若使用已经训练好的权重,可以执行这部分语言,并且跳过下面模型训练部分

In [16]
!mkdir output/
!mkdir output/ResNet50_vd/
!mkdir output/VGG16/
!mkdir output/PPLCNetV2_base/
       
mkdir: 无法创建目录"output/": 文件已存在
mkdir: 无法创建目录"output/ResNet50_vd/": 文件已存在
mkdir: 无法创建目录"output/VGG16/": 文件已存在
mkdir: 无法创建目录"output/PPLCNetV2_base/": 文件已存在
       
In [17]
!cp ../work/ResNet50_vd/best_model.pdparams ./output/ResNet50_vd/
!cp ../work/VGG16/best_model.pdparams ./output/VGG16/
!cp ../work/PPLCNetv2/best_model.pdparams ./output/PPLCNetV2_base/
   

6 模型训练

若使用上面已经训练好的模型,可以跳过模型训练部分

下面介绍以work/PPLCNetV2_base.yaml为例,修改对应模型的相关配置 因为是单卡训练,加入预训练模型后,对应学习率应该降为原先的1/4~1/5,而num_workers则设置为0。Art数据集一共有49个作者,所以对应class_num应该设置为49。class_id_map_file: /home/aistudio/data/Art/label_list.txt则设置为对应的标签文本。- TopkAcc则设置为对应[1,49]

# global configsGlobal:
  checkpoints: null
  pretrained_model: ../work/PPLCNetv2/PPLCNetV2_base_pretrained
  output_dir: ./output/
  device: gpu
  save_interval: 1
  eval_during_train: True
  eval_interval: 1
  epochs: 480
  print_batch_step: 10
  use_visualdl: False
  # used for static mode and model export
  image_shape: [3, 224, 224]  save_inference_dir: ./inference# model architectureArch:
  name: PPLCNetV2_base
  class_num: 49# loss function config for traing/eval processLoss:
  Train:
    - CELoss:
        weight: 1.0
        epsilon: 0.1
  Eval:
    - CELoss:
        weight: 1.0Optimizer:
  name: Momentum
  momentum: 0.9
  lr:
    name: Cosine
    learning_rate: 0.016
    warmup_epoch: 5
  regularizer:
    name: 'L2'
    coeff: 0.00004# data loader for train and evalDataLoader:
  Train:
    dataset:
      name: MultiScaleDataset
      image_root: ../data/
      cls_label_path: ../data/Art/train_list.txt
      transform_ops:
        - DecodeImage:
            to_rgb: True
            channel_first: False
        - RandCropImage:
            size: 224
        - RandFlipImage:
            flip_code: 1
        - NormalizeImage:
            scale: 1.0/255.0
            mean: [0.485, 0.456, 0.406]            std: [0.229, 0.224, 0.225]            order: ''

    # support to specify width and height respectively:
    # scales: [(160,160), (192,192), (224,224) (288,288) (320,320)]
    sampler:
      name: MultiScaleSampler
      scales: [160, 192, 224, 288, 320]      # first_bs: batch size for the first image resolution in the scales list
      # divide_factor: to ensure the width and height dimensions can be devided by downsampling multiple
      first_bs: 500
      divided_factor: 32
      is_training: True
    loader:
      num_workers: 0
      use_shared_memory: True

  Eval:
    dataset: 
      name: ImageNetDataset
      image_root: ../data/
      cls_label_path: ../data/Art/val_list.txt
      transform_ops:
        - DecodeImage:
            to_rgb: True
            channel_first: False
        - ResizeImage:
            resize_short: 256
        - CropImage:
            size: 224
        - NormalizeImage:
            scale: 1.0/255.0
            mean: [0.485, 0.456, 0.406]            std: [0.229, 0.224, 0.225]            order: ''
    sampler:
      name: DistributedBatchSampler
      batch_size: 64
      drop_last: False
      shuffle: False
    loader:
      num_workers: 0
      use_shared_memory: TrueInfer:
  infer_imgs: ../data/Art/img/974.jpg
  batch_size: 10
  transforms:
    - DecodeImage:
        to_rgb: True
        channel_first: False
    - ResizeImage:
        resize_short: 256
    - CropImage:
        size: 224
    - NormalizeImage:
        scale: 1.0/255.0
        mean: [0.485, 0.456, 0.406]        std: [0.229, 0.224, 0.225]        order: ''
    - ToCHWImage:
  PostProcess:
    name: Topk
    topk: 5
    class_id_map_file: /home/aistudio/data/Art/label_list.txtMetric:
  Train:
    - TopkAcc:
        topk: [1, 49]  Eval:
    - TopkAcc:
        topk: [1, 49]
   

默认使用已经训练好的权重,如若自己训练模型,取消下面部分代码注释

6.1训练ResNet50_vd模型

In [18]
#!python3 tools/train.py -c ./ppcls/configs/quick_start/ResNet50_vd.yaml -o Global.device=gpu
   

6.2练VGG16模型

In [19]
#!python3 tools/train.py -c ./ppcls/configs/ImageNet/VGG/VGG16.yaml -o Global.device=gpu
   

6.3训练PPLCNetV2模型

In [20]
#!python3 tools/train.py -c ./ppcls/configs/ImageNet/PPLCNetV2/PPLCNetV2_base.yaml -o Global.device=gpu
   

7 模型评估

7.1 ResNet50_vd模型评估

In [ ]
!python tools/eval.py \
    -c ./ppcls/configs/quick_start/ResNet50_vd.yaml \
    -o Global.pretrained_model=./output/ResNet50_vd/best_model
   

最后ResNet50_vd模型在验证集的验证准确率达到了99.44%,实际情况可能有些许波动,但已经达到预期结果

7.2 VGG16模型评估

In [ ]
!python tools/eval.py \
    -c ./ppcls/configs/ImageNet/VGG/VGG16.yaml \
    -o Global.pretrained_model=./output/VGG16/best_model
   

最后VGG16模型在验证集的验证准确率达到了72.33%,实际情况可能有些许波动,识别结果在可接受范围内,有待进一步优化改进

7.3 PPLCNetV2模型评估

In [ ]
!python tools/eval.py \
    -c ./ppcls/configs/ImageNet/PPLCNetV2/PPLCNetV2_base.yaml \
    -o Global.pretrained_model=./output/PPLCNetV2_base/best_model
   

最后PPLCNetV2模型在验证集的验证准确率达到了95.57%,实际情况可能有些许波动,但已经达到预期结果

8 艺术品作者识别

从网上上下载一副Edgar Degas的作品进行识别

【AI达人特训营】多模型集成学习的艺术作品作者识别 - php中文网        

8.1 多模型分别进行预测

分别使用PaddleClas调用三个已经训练的模型对输入图片进行识别,并将识别的艺术品作者结果保存在result.txt文件内,方便后续进行多模型集成学习

In [ ]
# 修改Infer.infer_imgs为待识别艺术品图片路径file = open("result.txt", 'w').close()
!python3 tools/infer.py \
    -c ./ppcls/configs/quick_start/ResNet50_vd.yaml \
    -o Infer.infer_imgs=../images/EdgarDegas.jpeg \
    -o Global.pretrained_model=output/ResNet50_vd/best_model
!python3 tools/infer.py \
    -c ./ppcls/configs/ImageNet/VGG/VGG16.yaml \
    -o Infer.infer_imgs=../images/EdgarDegas.jpeg \
    -o Global.pretrained_model=./output/VGG16/best_model
!python3 tools/infer.py \
    -c ./ppcls/configs/ImageNet/PPLCNetV2/PPLCNetV2_base.yaml \
    -o Infer.infer_imgs=../images/EdgarDegas.jpeg \
    -o Global.pretrained_model=./output/PPLCNetV2_base/best_model
   

从result.txt文件中分别读取每个模型对艺术作品的识别结果

In [25]
SaveList=[]with open("result.txt", "r", encoding='utf-8') as file:    for line in file:
        line = line.strip('\n')
        SaveList.append(line)
    file.close()

list_temp=[SaveList[0],SaveList[1],SaveList[2]]print("ResNet50_vd模型预测结果:{0},VGG16模型预测结果:{1},PPLCNetV2模型预测结果:{2}".format(SaveList[0],SaveList[1],SaveList[2]))
       
ResNet50_vd模型预测结果:Edgar Degas,VGG16模型预测结果:Edgar Degas,PPLCNetV2模型预测结果:Edgar Degas
       

8.2 多模型融合部分

通过多模型集成学习可以解决单一模型精度不足,识别效果欠缺的问题,这里集成学习采用硬投票方式,也可以换用其他更高效的集成学习方式

In [26]
import collections

m=collections.Counter(list_temp)
temp_max,key_max=0,0for k,v in m.items():    if v>temp_max:
        temp_max=v
        key_max=kprint("多模型集成学习后的预测结果是:"+key_max)
       
多模型集成学习后的预测结果是:Edgar Degas
       

可见三个模型都给出了一样的预测结果,最后多模型集成的预测结果也是Edgar Degas,符合预期

In [ ]
# 修改Infer.infer_imgs为待识别艺术品图片路径file = open("result.txt", 'w').close()
!python3 tools/infer.py \
    -c ./ppcls/configs/quick_start/ResNet50_vd.yaml \
    -o Infer.infer_imgs=../images/Rembrandt.jpeg \
    -o Global.pretrained_model=output/ResNet50_vd/best_model
!python3 tools/infer.py \
    -c ./ppcls/configs/ImageNet/VGG/VGG16.yaml \
    -o Infer.infer_imgs=../images/Rembrandt.jpeg \
    -o Global.pretrained_model=./output/VGG16/best_model
!python3 tools/infer.py \
    -c ./ppcls/configs/ImageNet/PPLCNetV2/PPLCNetV2_base.yaml \
    -o Infer.infer_imgs=../images/Rembrandt.jpeg \
    -o Global.pretrained_model=./output/PPLCNetV2_base/best_model
   

8.3 多模型集成学习的纠正预测

接下来测试一下从网上获取的Rembrandt的作品

【AI达人特训营】多模型集成学习的艺术作品作者识别 - php中文网        

在对Rembrandt作品进行识别时,ResNet50_vd模型预测结果是Rembrandt,PPLCNetV2模型预测结果是Rembrandt,而VGG16模型预测结果却是Titian,第二预测结果才是Rembrandt,显而易见VGG16模型得到了错误的预测。最终因为多模型集成效果,即使单一VGG16模型出现错误预测,其他的分类器也将错误纠正回来,得到正确的预测结果Rembrandt,可见多模型集成学习对识别效果有很大提升。

In [35]
import collections

SaveList=[]with open("result.txt", "r", encoding='utf-8') as file:    for line in file:
        line = line.strip('\n')
        SaveList.append(line)
    file.close()

list_temp=[SaveList[0],SaveList[1],SaveList[2]]print("ResNet50_vd模型预测结果:{0},VGG16模型预测结果:{1},PPLCNetV2模型预测结果:{2}".format(SaveList[0],SaveList[1],SaveList[2]))
m=collections.Counter(list_temp)
temp_max,key_max=0,0for k,v in m.items():    if v>temp_max:
        temp_max=v
        key_max=kprint("多模型集成学习后的预测结果是:"+key_max)
       
ResNet50_vd模型预测结果:Rembrandt,VGG16模型预测结果:Titian,PPLCNetV2模型预测结果:Rembrandt
多模型集成学习后的预测结果是:Rembrandt
       

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

49

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

89

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

276

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

59

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

99

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

105

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

230

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

619

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

173

2026.03.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号