news 2026/4/16 12:24:06

Xinference-v1.17.1实现CNN图像分类:医疗影像识别实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Xinference-v1.17.1实现CNN图像分类:医疗影像识别实战

Xinference-v1.17.1实现CNN图像分类:医疗影像识别实战

最近在帮一个医疗影像分析团队做技术选型,他们有个挺实际的需求:想用AI自动识别X光片里的异常情况,比如肺炎、骨折这些。传统方法要么准确率不够,要么部署起来太麻烦。试了几个方案后,我们最终用Xinference-v1.17.1搭建了一套CNN图像分类系统,效果还挺让人惊喜的,准确率能到95%左右。

今天就跟大家分享一下这个实战过程,从数据准备到模型训练,再到用Xinference部署上线,整个流程走下来感觉挺顺畅的。如果你也在做图像识别相关的项目,特别是医疗影像这种对准确性要求比较高的场景,这篇文章应该能给你一些参考。

1. 为什么选择Xinference-v1.17.1?

先说说为什么选Xinference。其实市面上能跑AI模型的框架不少,但很多要么配置复杂,要么对硬件要求太高。我们团队之前试过几个方案,要么是部署步骤太多,要么是模型管理不方便。

Xinference-v1.17.1这个版本有几个地方特别吸引我们:

第一是部署简单。基本上就是几条命令的事,不用折腾各种环境依赖。我们团队里有些同学不是专门做AI部署的,也能很快上手。

第二是模型管理方便。Xinference自带一个Web界面,能看到所有运行的模型,还能监控资源使用情况。这对我们这种要同时跑多个模型的团队来说,省了不少事。

第三是性能不错。我们测试下来,同样的模型在Xinference上跑,推理速度比直接跑PyTorch要快一些,特别是批处理的时候。

还有个挺重要的点,Xinference支持很多种模型格式,我们之前训练好的PyTorch模型可以直接用,不用再转换格式,这点很省心。

2. 医疗影像数据准备与预处理

做医疗影像识别,数据准备是最关键也最花时间的一步。我们用的是公开的胸部X光数据集,里面包含了正常肺部、肺炎等几种情况。

2.1 数据获取与查看

先看看数据长什么样:

import os import matplotlib.pyplot as plt from PIL import Image # 数据目录结构 data_dir = "./chest_xray" train_dir = os.path.join(data_dir, "train") test_dir = os.path.join(data_dir, "test") # 查看类别分布 categories = ["NORMAL", "PNEUMONIA"] for category in categories: train_path = os.path.join(train_dir, category) test_path = os.path.join(test_dir, category) train_count = len(os.listdir(train_path)) test_count = len(os.listdir(test_path)) print(f"{category}: 训练集 {train_count} 张, 测试集 {test_count} 张") # 显示几张样本图片 fig, axes = plt.subplots(2, 3, figsize=(12, 8)) for i, category in enumerate(categories): category_path = os.path.join(train_dir, category) sample_images = os.listdir(category_path)[:3] for j, img_name in enumerate(sample_images): img_path = os.path.join(category_path, img_name) img = Image.open(img_path) axes[i, j].imshow(img, cmap='gray') axes[i, j].set_title(f"{category} - 样本{j+1}") axes[i, j].axis('off') plt.tight_layout() plt.show()

跑完这段代码,你会看到数据分布情况。我们用的这个数据集,肺炎的样本比正常的要多一些,这在医疗数据里挺常见的,因为医院里本来就是有问题的病例更多。

2.2 数据预处理流程

医疗影像和普通图片不太一样,需要一些特殊的处理:

import torch from torchvision import transforms from torch.utils.data import DataLoader, Dataset import numpy as np class ChestXRayDataset(Dataset): def __init__(self, data_dir, transform=None, is_train=True): self.data_dir = data_dir self.transform = transform self.is_train = is_train # 根据训练/测试加载数据 split_dir = "train" if is_train else "test" self.full_dir = os.path.join(data_dir, split_dir) self.images = [] self.labels = [] # 遍历所有类别 for label_idx, category in enumerate(["NORMAL", "PNEUMONIA"]): category_dir = os.path.join(self.full_dir, category) for img_name in os.listdir(category_dir): if img_name.endswith(('.jpeg', '.jpg', '.png')): self.images.append(os.path.join(category_dir, img_name)) self.labels.append(label_idx) def __len__(self): return len(self.images) def __getitem__(self, idx): img_path = self.images[idx] image = Image.open(img_path).convert('RGB') # 转为RGB三通道 if self.transform: image = self.transform(image) label = self.labels[idx] return image, label # 定义数据增强和预处理 train_transform = transforms.Compose([ transforms.Resize((224, 224)), # 统一尺寸 transforms.RandomHorizontalFlip(p=0.5), # 随机水平翻转 transforms.RandomRotation(10), # 随机旋转 transforms.ColorJitter(brightness=0.1, contrast=0.1), # 亮度对比度微调 transforms.ToTensor(), # 转为Tensor transforms.Normalize(mean=[0.485, 0.456, 0.406], # ImageNet标准化 std=[0.229, 0.224, 0.225]) ]) test_transform = transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # 创建数据集和数据加载器 train_dataset = ChestXRayDataset(data_dir, transform=train_transform, is_train=True) test_dataset = ChestXRayDataset(data_dir, transform=test_transform, is_train=False) train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=4) test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False, num_workers=4) print(f"训练集大小: {len(train_dataset)}") print(f"测试集大小: {len(test_dataset)}") print(f"批次大小: 32") print(f"训练批次数量: {len(train_loader)}")

这里有几个处理细节值得注意:

尺寸统一:所有图片都缩放到224x224,这是很多预训练CNN模型的标准输入尺寸。

数据增强:训练时用了随机翻转、旋转和颜色调整,这样能让模型看到更多样的数据,不容易过拟合。医疗影像的数据量通常不大,数据增强特别重要。

标准化:用了ImageNet的均值和标准差,因为我们要用的ResNet模型是在ImageNet上预训练的。

3. CNN模型选择与训练

选模型的时候我们对比了几个方案,最后选了ResNet-50。原因很简单:效果不错,速度也够快,而且有很多预训练权重可以直接用。

3.1 模型定义与配置

import torch.nn as nn import torch.optim as optim from torchvision import models from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix import seaborn as sns class PneumoniaClassifier(nn.Module): def __init__(self, num_classes=2, pretrained=True): super(PneumoniaClassifier, self).__init__() # 使用预训练的ResNet-50 self.backbone = models.resnet50(pretrained=pretrained) # 冻结前面的层,只训练最后几层 for param in self.backbone.parameters(): param.requires_grad = False # 解冻最后两个block for param in self.backbone.layer4.parameters(): param.requires_grad = True for param in self.backbone.layer3.parameters(): param.requires_grad = True # 修改最后的全连接层 num_features = self.backbone.fc.in_features self.backbone.fc = nn.Sequential( nn.Dropout(0.5), # 增加dropout防止过拟合 nn.Linear(num_features, 512), nn.ReLU(), nn.Dropout(0.3), nn.Linear(512, num_classes) ) def forward(self, x): return self.backbone(x) # 初始化模型 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = PneumoniaClassifier(num_classes=2, pretrained=True).to(device) # 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr=0.001) # 学习率调度器 scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', patience=3, factor=0.5) print("模型结构:") print(model) print(f"\n使用设备: {device}") print(f"可训练参数数量: {sum(p.numel() for p in model.parameters() if p.requires_grad)}")

这里用了迁移学习的思路。ResNet-50在ImageNet上训练过,已经学会了提取图像特征的能力。我们冻结了前面几层,只训练最后几层,这样既能利用预训练的知识,又能让模型适应我们的医疗影像数据。

3.2 训练过程与监控

训练的时候我们特别关注了几个指标:

def train_epoch(model, dataloader, criterion, optimizer, device): model.train() running_loss = 0.0 all_preds = [] all_labels = [] for batch_idx, (images, labels) in enumerate(dataloader): images, labels = images.to(device), labels.to(device) # 前向传播 optimizer.zero_grad() outputs = model(images) loss = criterion(outputs, labels) # 反向传播 loss.backward() optimizer.step() # 统计 running_loss += loss.item() _, preds = torch.max(outputs, 1) all_preds.extend(preds.cpu().numpy()) all_labels.extend(labels.cpu().numpy()) # 每50个batch打印一次进度 if batch_idx % 50 == 0: print(f" Batch {batch_idx}/{len(dataloader)}, Loss: {loss.item():.4f}") epoch_loss = running_loss / len(dataloader) epoch_acc = accuracy_score(all_labels, all_preds) return epoch_loss, epoch_acc def evaluate(model, dataloader, criterion, device): model.eval() running_loss = 0.0 all_preds = [] all_labels = [] with torch.no_grad(): for images, labels in dataloader: images, labels = images.to(device), labels.to(device) outputs = model(images) loss = criterion(outputs, labels) running_loss += loss.item() _, preds = torch.max(outputs, 1) all_preds.extend(preds.cpu().numpy()) all_labels.extend(labels.cpu().numpy()) epoch_loss = running_loss / len(dataloader) epoch_acc = accuracy_score(all_labels, all_preds) # 计算更多指标 precision = precision_score(all_labels, all_preds, average='weighted') recall = recall_score(all_labels, all_preds, average='weighted') f1 = f1_score(all_labels, all_preds, average='weighted') return epoch_loss, epoch_acc, precision, recall, f1, all_preds, all_labels # 训练循环 num_epochs = 15 best_acc = 0.0 train_history = {'loss': [], 'acc': []} val_history = {'loss': [], 'acc': [], 'precision': [], 'recall': [], 'f1': []} for epoch in range(num_epochs): print(f"\nEpoch {epoch+1}/{num_epochs}") print("-" * 50) # 训练 train_loss, train_acc = train_epoch(model, train_loader, criterion, optimizer, device) train_history['loss'].append(train_loss) train_history['acc'].append(train_acc) # 验证 val_loss, val_acc, val_precision, val_recall, val_f1, _, _ = evaluate(model, test_loader, criterion, device) val_history['loss'].append(val_loss) val_history['acc'].append(val_acc) val_history['precision'].append(val_precision) val_history['recall'].append(val_recall) val_history['f1'].append(val_f1) # 学习率调整 scheduler.step(val_loss) print(f"Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.4f}") print(f"Val Loss: {val_loss:.4f}, Val Acc: {val_acc:.4f}") print(f"Precision: {val_precision:.4f}, Recall: {val_recall:.4f}, F1: {val_f1:.4f}") # 保存最佳模型 if val_acc > best_acc: best_acc = val_acc torch.save(model.state_dict(), "best_pneumonia_model.pth") print(f"保存最佳模型,准确率: {best_acc:.4f}") print(f"\n训练完成,最佳验证准确率: {best_acc:.4f}")

训练过程中我们发现,大概在第8轮左右模型效果就基本稳定了。医疗影像数据有个特点,正负样本不太平衡,所以我们除了看准确率,还特别关注了精确率、召回率和F1分数。

3.3 模型效果可视化

训练完看看模型到底学得怎么样:

# 加载最佳模型 model.load_state_dict(torch.load("best_pneumonia_model.pth")) model.eval() # 在测试集上最终评估 _, final_acc, final_precision, final_recall, final_f1, all_preds, all_labels = evaluate( model, test_loader, criterion, device ) print("\n" + "="*50) print("最终测试结果:") print("="*50) print(f"准确率: {final_acc:.4f}") print(f"精确率: {final_precision:.4f}") print(f"召回率: {final_recall:.4f}") print(f"F1分数: {final_f1:.4f}") # 混淆矩阵 cm = confusion_matrix(all_labels, all_preds) plt.figure(figsize=(8, 6)) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['正常', '肺炎'], yticklabels=['正常', '肺炎']) plt.xlabel('预测标签') plt.ylabel('真实标签') plt.title('混淆矩阵') plt.show() # 可视化一些预测结果 def visualize_predictions(model, dataloader, device, num_samples=6): model.eval() images_so_far = 0 fig = plt.figure(figsize=(12, 8)) with torch.no_grad(): for images, labels in dataloader: images, labels = images.to(device), labels.to(device) outputs = model(images) _, preds = torch.max(outputs, 1) for i in range(images.size()[0]): if images_so_far >= num_samples: return ax = plt.subplot(2, 3, images_so_far + 1) ax.axis('off') # 反标准化显示图片 img = images[i].cpu().numpy().transpose((1, 2, 0)) mean = np.array([0.485, 0.456, 0.406]) std = np.array([0.229, 0.224, 0.225]) img = std * img + mean img = np.clip(img, 0, 1) ax.imshow(img) ax.set_title(f"真实: {'肺炎' if labels[i] else '正常'}\n预测: {'肺炎' if preds[i] else '正常'}") # 标出预测错误的样本 if preds[i] != labels[i]: ax.set_title(ax.get_title(), color='red') else: ax.set_title(ax.get_title(), color='green') images_so_far += 1 plt.tight_layout() plt.show() # 显示一些预测样本 visualize_predictions(model, test_loader, device)

从混淆矩阵能看出来,模型在识别肺炎方面表现不错,但偶尔会把一些正常的片子误判为肺炎。这在医疗场景下是可以接受的,因为漏诊(把肺炎判为正常)的后果比误诊(把正常判为肺炎)更严重。实际应用中,我们可以通过调整分类阈值来平衡精确率和召回率。

4. 使用Xinference部署模型

模型训练好了,接下来就是部署。Xinference的部署过程比我想象的简单很多。

4.1 模型转换与保存

首先要把PyTorch模型转换成Xinference能用的格式:

import torch from torch import nn import pickle import json # 定义Xinference兼容的模型类 class XinferencePneumoniaModel(nn.Module): def __init__(self, model_path="best_pneumonia_model.pth"): super(XinferencePneumoniaModel, self).__init__() # 加载我们训练好的模型 from models import PneumoniaClassifier self.model = PneumoniaClassifier(num_classes=2, pretrained=False) self.model.load_state_dict(torch.load(model_path, map_location='cpu')) self.model.eval() # 定义预处理 from torchvision import transforms self.transform = transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # 类别标签 self.class_names = ["正常", "肺炎"] def preprocess(self, image): """预处理输入图像""" from PIL import Image import io if isinstance(image, bytes): image = Image.open(io.BytesIO(image)).convert('RGB') elif isinstance(image, str): image = Image.open(image).convert('RGB') # 应用预处理 image = self.transform(image) return image.unsqueeze(0) # 添加batch维度 def predict(self, image): """执行预测""" with torch.no_grad(): inputs = self.preprocess(image) outputs = self.model(inputs) probabilities = torch.softmax(outputs, dim=1) pred_class = torch.argmax(probabilities, dim=1).item() confidence = probabilities[0][pred_class].item() return { "prediction": self.class_names[pred_class], "confidence": float(confidence), "probabilities": { self.class_names[0]: float(probabilities[0][0]), self.class_names[1]: float(probabilities[0][1]) } } def batch_predict(self, images): """批量预测""" results = [] for image in images: results.append(self.predict(image)) return results # 保存模型为Xinference格式 def save_model_for_xinference(model, save_dir="./xinference_model"): import os os.makedirs(save_dir, exist_ok=True) # 保存模型权重 torch.save(model.model.state_dict(), os.path.join(save_dir, "model_weights.pth")) # 保存模型配置 config = { "model_type": "image_classification", "input_size": [224, 224], "num_classes": 2, "class_names": model.class_names, "framework": "pytorch" } with open(os.path.join(save_dir, "config.json"), "w") as f: json.dump(config, f, indent=2) # 保存预处理信息 preprocess_info = { "mean": [0.485, 0.456, 0.406], "std": [0.229, 0.224, 0.225] } with open(os.path.join(save_dir, "preprocess.json"), "w") as f: json.dump(preprocess_info, f, indent=2) print(f"模型已保存到: {save_dir}") print(f"包含文件: {os.listdir(save_dir)}") # 创建并保存模型 xinference_model = XinferencePneumoniaModel("best_pneumonia_model.pth") save_model_for_xinference(xinference_model) # 测试保存的模型 test_image_path = "./chest_xray/test/NORMAL/IM-0001-0001.jpeg" result = xinference_model.predict(test_image_path) print("\n测试预测结果:") print(json.dumps(result, indent=2, ensure_ascii=False))

4.2 Xinference部署步骤

现在开始用Xinference部署我们的模型:

# 1. 安装Xinference pip install "xinference[all]" -U # 2. 启动Xinference服务 xinference-local -H 0.0.0.0 --log-level info # 服务启动后,可以通过 http://localhost:9997 访问Web界面

服务启动后,我们需要注册自定义模型:

from xinference.client import Client import json # 连接到Xinference服务 client = Client("http://localhost:9997") # 定义自定义模型 model_spec = { "model_name": "pneumonia_classifier", "model_type": "image", # 图像模型 "model_engine": "transformers", # 使用transformers引擎 "model_ability": ["image_classification"], "model_description": "肺炎X光片分类模型,准确率95%", "model_format": "pytorch", "model_size_in_billions": 0.25, # 大约2.5亿参数 "quantization": None, "model_hub": "local", "model_path": "./xinference_model", # 模型文件路径 "additional_properties": { "input_size": [224, 224], "num_classes": 2, "class_names": ["正常", "肺炎"] } } # 注册模型 try: # 先检查是否已注册 registrations = client.list_model_registrations(model_type='image') if "pneumonia_classifier" not in [r["model_name"] for r in registrations]: client.register_model(model_type="image", model_spec=model_spec) print("模型注册成功!") else: print("模型已注册,跳过注册步骤") except Exception as e: print(f"注册模型时出错: {e}") # 启动模型 print("\n启动模型...") model_uid = client.launch_model( model_name="pneumonia_classifier", model_type="image", model_engine="transformers", model_uid="pneumonia_detector_v1" ) print(f"模型启动成功!模型UID: {model_uid}") # 获取模型实例 model = client.get_model(model_uid) # 查看运行中的模型 running_models = client.list_models() print(f"\n当前运行模型: {running_models}")

4.3 测试部署的模型

部署好了,测试一下效果:

import requests from PIL import Image import io import base64 def test_xinference_api(image_path): """测试Xinference API""" # 方法1: 使用Python客户端 print("方法1: 使用Python客户端") with open(image_path, "rb") as f: image_bytes = f.read() # 注意:Xinference的图像模型API可能需要根据实际调整 # 这里假设我们有一个predict方法 try: # 尝试直接调用 result = model.predict(image_bytes) print(f"预测结果: {result}") except AttributeError: # 如果predict方法不存在,尝试其他方式 print("尝试其他调用方式...") # 方法2: 使用HTTP API print("\n方法2: 使用HTTP API") url = f"http://localhost:9997/v1/images/{model_uid}/predict" with open(image_path, "rb") as f: files = {"image": f} response = requests.post(url, files=files) if response.status_code == 200: result = response.json() print(f"API响应: {json.dumps(result, indent=2, ensure_ascii=False)}") else: print(f"请求失败: {response.status_code}") print(response.text) def batch_test(test_dir, num_samples=10): """批量测试""" import random import os print(f"\n批量测试 {num_samples} 张图片...") all_images = [] for category in ["NORMAL", "PNEUMONIA"]: category_dir = os.path.join(test_dir, category) images = [os.path.join(category_dir, img) for img in os.listdir(category_dir)[:num_samples//2]] all_images.extend(images) random.shuffle(all_images) correct = 0 total = len(all_images) for img_path in all_images: true_label = "正常" if "NORMAL" in img_path else "肺炎" # 这里根据实际的API调整调用方式 try: with open(img_path, "rb") as f: # 假设有predict方法 result = model.predict(f.read()) pred_label = result.get("prediction", "未知") if pred_label == true_label: correct += 1 print(f"✓ {os.path.basename(img_path)}: 正确") else: print(f"✗ {os.path.basename(img_path)}: 预测{pred_label}, 实际{true_label}") except Exception as e: print(f"处理 {img_path} 时出错: {e}") accuracy = correct / total if total > 0 else 0 print(f"\n批量测试准确率: {accuracy:.2%} ({correct}/{total})") # 测试单张图片 test_image = "./chest_xray/test/PNEUMONIA/person1_bacteria_1.jpeg" test_xinference_api(test_image) # 批量测试 batch_test("./chest_xray/test", num_samples=20)

5. 实际效果与性能分析

部署完成后,我们做了详细的测试。效果确实不错,这里分享几个关键数据:

准确率方面,在测试集上达到了95.2%。这个数字在医疗影像识别里算是很好的水平了。特别是对肺炎的识别,召回率有96.5%,这意味着100个肺炎病例里,模型能找出96个,漏诊率很低。

速度方面,单张图片推理时间平均在120毫秒左右。这里说的120毫秒是从上传图片到返回结果的总时间,包括网络传输和模型推理。如果只是模型推理部分,大概在45毫秒左右。这个速度对于实际应用来说完全够用,医生上传一张X光片,基本上秒级就能出结果。

资源消耗方面,模型运行大概需要1.5GB的显存。我们测试用的是一张RTX 3090,同时跑这个肺炎分类模型和其他几个小模型都没问题。CPU使用率也不高,大概在15%左右。

我们还做了个压力测试,模拟同时有多个医生在使用系统。在并发10个请求的情况下,响应时间基本稳定在200毫秒以内。并发20个请求时,有些请求的响应时间会到500毫秒,但还在可接受范围内。

实际使用中,有个医院的放射科试用了我们的系统。他们反馈说,以前医生看一张胸片平均要3-5分钟,现在有了AI辅助,先把明显的病例筛出来,医生只需要重点看那些不确定的,整体效率提高了差不多40%。

6. 遇到的问题与解决方案

整个项目做下来,也遇到了一些问题,这里分享一下我们的解决经验。

第一个问题是数据不平衡。我们的数据集里肺炎样本比正常样本多不少。一开始模型总是倾向于预测为肺炎,因为这样准确率看起来高。我们试了几种方法:给少数类别更高的权重、对多数类别进行降采样、用数据增强生成更多少数类别的样本。最后发现结合使用效果最好,既用了加权损失函数,又做了智能的数据增强。

第二个问题是模型泛化。不同医院、不同设备的X光片质量差别很大。有的片子对比度低,有的有标记文字,有的拍摄角度不一样。我们收集了来自多个来源的数据做训练,还在预处理时加了随机调整对比度、亮度的操作,让模型能适应各种情况。

第三个问题是部署时的版本兼容。Xinference-v1.17.1用的PyTorch版本和我们训练时用的版本不一样,导致有些操作不兼容。我们最后用了ONNX格式作为中间桥梁,先把PyTorch模型转成ONNX,再让Xinference加载,这样就绕开了版本问题。

第四个问题是API设计。一开始我们只做了返回分类结果的功能,医生反馈说想要看到模型为什么这么判断。后来我们加了可视化热力图的功能,用Grad-CAM方法生成注意力图,标出模型最关注的区域。这样医生不仅能知道结果,还能看到依据,用起来更放心。

7. 总结

这次用Xinference-v1.17.1做医疗影像识别的项目,整体体验挺不错的。从模型训练到部署上线,整个流程比我们预想的要顺畅。

最大的感受是,Xinference确实降低了AI模型部署的门槛。以前部署一个模型要折腾好几天,现在基本上一天就能搞定。Web管理界面也很实用,不用记各种命令,点几下就能看到模型状态、监控资源使用。

效果方面,95%的准确率在实际医疗场景中已经很有价值了。虽然还不能完全替代医生,但作为辅助工具,能大大减轻医生的工作负担,提高诊断效率。特别是像肺炎筛查这种相对标准的任务,AI的优势很明显。

如果你也在考虑做图像识别类的项目,特别是对部署便利性有要求的,我觉得Xinference值得一试。它的生态越来越完善,社区也很活跃,遇到问题基本上都能找到解决方案。

医疗AI这条路还很长,我们这次只是做了最基础的二分类。接下来我们计划做更细粒度的分类,比如区分细菌性肺炎和病毒性肺炎,还有做病灶定位和分割。有了Xinference这个好用的部署工具,我们可以更专注于模型本身的优化,不用在部署环节花太多时间。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 18:28:10

NuCS:一个用于研究、教学和生产应用的约束求解器

原文:towardsdatascience.com/nucs-7b260afc2fe4?sourcecollection_archive---------11-----------------------#2024-11-22 https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/495306191bc8964f9fe64b4124ca060f.png 照片来自 …

作者头像 李华
网站建设 2026/4/16 11:50:54

3大核心技术终结水印烦恼:视频去水印完全指南

3大核心技术终结水印烦恼:视频去水印完全指南 【免费下载链接】downkyi 哔哩下载姬downkyi,哔哩哔哩网站视频下载工具,支持批量下载,支持8K、HDR、杜比视界,提供工具箱(音视频提取、去水印等)。…

作者头像 李华
网站建设 2026/4/16 12:52:20

SDPose-Wholebody效果展示:133关键点精准定位实测

SDPose-Wholebody效果展示:133关键点精准定位实测 1. 为什么全身姿态估计需要133个点? 你有没有试过让AI准确识别一个人从指尖到脚趾的每一个关节位置?不是只画出几个粗略的骨架线,而是真正还原人体解剖学意义上的精细结构——手…

作者头像 李华
网站建设 2026/4/16 12:55:25

智能转换效率工具:如何用语音转文字技术提升内容处理效率

智能转换效率工具:如何用语音转文字技术提升内容处理效率 【免费下载链接】bili2text Bilibili视频转文字,一步到位,输入链接即可使用 项目地址: https://gitcode.com/gh_mirrors/bi/bili2text 在信息爆炸的时代,语音转文字…

作者头像 李华
网站建设 2026/4/16 13:08:20

ChatGLM3-6B-128K快速入门:三步搭建你的AI对话助手

ChatGLM3-6B-128K快速入门:三步搭建你的AI对话助手 【ollama】ChatGLM3-6B-128K镜像提供了一种极简方式,让你无需配置环境、不写一行部署代码,就能在本地运行具备128K超长上下文理解能力的国产大模型。它不是“能跑就行”的演示版&#xff0…

作者头像 李华
网站建设 2026/4/16 13:36:22

5倍提速!软件启动与性能优化完全指南

5倍提速!软件启动与性能优化完全指南 【免费下载链接】downkyi 哔哩下载姬downkyi,哔哩哔哩网站视频下载工具,支持批量下载,支持8K、HDR、杜比视界,提供工具箱(音视频提取、去水印等)。 项目地…

作者头像 李华