当前位置: 首页 > article >正文

李哥深度学习班学习笔记——图像识别

一、导入依赖库​ import random #用于设置随机种子保证实验可复现 import torch #Pytorh核心库构建和训练神经网络 import torch.nn as nn #Pytorch神经网络层模块 import numpy as np #数值计算库处理矩阵 import os #操作系统交互处理文件路径 from PIL import Image #读取图片数据 from torch.utils.data import Dataset, DataLoader #自定义数据集和数据加载器 from tqdm import tqdm #进度条显示方便查看数据加载和训练进度 from torchvision import transforms #图像预处理裁剪、旋转、转张量等 import time #计时统计训练耗时 import matplotlib.pyplot as plt #绘制loss和acc曲线 from model_utils.model import initialize_model #自定义函数初始化预训练模型 ​二、读取数据集1.初始化方法Dataset是PyTorch的抽象类必须实现__init__/__getitem__/__len__三个方法用于定义数据加载逻辑。class food_Dataset(Dataset): #初始化方法 def __init__(self, path, modetrain): self.mode mode #保存数据模式train训练集/val验证集/semi半监督集 #semi模式只有图像没有标签其他模式有模式标签 if mode semi: self.X self.read_file(path) #X图像数据numpy数据shapeN224,224,3 else: self.X, self.Y self.read_file(path) self.Y torch.LongTensor(self.Y) #标签转为LongTensor if mode train: self.transform train_transform else: self.transform val_transform #读取文件方法 def read_file(self, path): #半监督学习读取无标签图像 if self.mode semi: file_list os.listdir(path) #列出路径下所有文件 xi np.zeros((len(file_list), HW, HW, 3), dtypenp.uint8) #初始化图像数组N张图224,224,3通道uint8类型 # 列出文件夹下所有文件名字 for j, img_name in enumerate(file_list): #遍历每个文件 img_path os.path.join(path, img_name) #拼接完整文件路径 img Image.open(img_path) #打开图片 img img.resize((HW, HW)) #统一大小缩放为224*224 xi[j, ...] img #将PIL图像转为numpy数组存入xi print(读到了%d个数据 % len(xi)) #打印读取数量 return xi #返回图像数据 #非半监督模式读取有标签图像 else: for i in tqdm(range(11)): #遍历11个类别 file_dir path /%02d % i #拼接类别文件夹路径 file_list os.listdir(file_dir) #列出该类别下所有文件 #初始化当前类别的图像/标签数组 xi np.zeros((len(file_list), HW, HW, 3), dtypenp.uint8) yi np.zeros(len(file_list), dtypenp.uint8) # 列出文件夹下所有文件名字 for j, img_name in enumerate(file_list): img_path os.path.join(file_dir, img_name) img Image.open(img_path) img img.resize((HW, HW)) xi[j, ...] img #存入图像 yi[j] i #存入标签当前类别i #合并所有类别的数据 if i 0: #第一类直接赋值 X xi Y yi else: #后续类别拼接axis0:按样本数维度拼接 #np.concatenate是合并不同类别的数据 X np.concatenate((X, xi), axis0) Y np.concatenate((Y, yi), axis0) print(读到了%d个数据 % len(Y)) #打印总数 return X, Y #返回图像标签 #获取单条数据方法训练时核心调用 def __getitem__(self, item): #半监督学习模式返回变换后的图像原始图像用于生成伪标签 if self.mode semi: return self.transform(self.X[item]), self.X[item] #非半监督模式返回变换后的图像标签 else: return self.transform(self.X[item]), self.Y[item] def __len__(self): return len(self.X)三、定义半监督学习数据集类生成伪标签半监督学习核心用训练好的模型给无标签数据打为标签筛选置信度高的样本加入训练。no_label_loader是无标签数据的DateLoaderthres0.99是置信度阈值只有模型预测置信度大于等于99%的样本才能被选为半监督样本保证伪标签准确。Softmax层将模型输出的logits转为概率dim1 表示按类别维度计算torch.no_grag()是推理模式的关键关闭梯度计算避免占用GPU内存class semiDataset(Dataset): #初始化方法 def __init__(self, no_label_loder, model, device, thres0.99): x, y self.get_label(no_label_loder, model, device, thres) #判断是否符合置信度的样本 if x []: self.flag False #无有效样本 else: self.flag True #有有效样本 self.X np.array(x) #为标签图像 self.Y torch.LongTensor(y) #伪标签转为LongTensor self.transform train_transform #用训练集变换 #生成伪标签方法 def get_label(self, no_label_loder, model, device, thres): model model.to(device) #模型迁移到指定设备GPU/CPU #初始化存储预测置信度、预测标签、有效图像、有效标签 pred_prob [] #预测置信度 labels [] #预测标签 x [] #有效图像 y [] #有效标签 #softmax层将模型输出的logits转为概率dim1表示按类别维度计算 soft nn.Softmax() #无梯度计算推理模式节省内存加快速度 with torch.no_grad(): #遍历无标签数据 for bat_x, _ in no_label_loder: bat_x bat_x.to(device)#数据移到设备 pred model(bat_x)#模型预测输出logits pred_soft soft(pred)#转为概率 #获取每个样本的最大概率置信度和对应标签 pred_max, pred_value pred_soft.max(1) #转为列表并存入 pred_prob.extend(pred_max.cpu().numpy().tolist()) labels.extend(pred_value.cpu().numpy().tolist()) #筛选置信度阈值的样本 for index, prob in enumerate(pred_prob): if prob thres: #加入有效图像原始图像 x.append(no_label_loder.dataset[index][1]) #调用到原始的getitem #加入对应伪标签 y.append(labels[index]) return x, y#返回有效图像和伪标签 def __getitem__(self, item): return self.transform(self.X[item]), self.Y[item] def __len__(self): return len(self.X)四、构建半监督数据加载器封装半监督数据的初始化逻辑返回DataLoader或NoneshffleFalse:半监督样本已筛选不能洗牌def get_semi_loader(no_label_loder, model, device, thres): # 初始化半监督数据集 semiset semiDataset(no_label_loder, model, device, thres) # 无有效样本返回None if semiset.flag False: return None # 有有效样本构建DataLoader else: semi_loader DataLoader(semiset, batch_size16, shuffleFalse) return semi_loader五、定义模型使用ResNet18进行迁移学习迁移学习把大佬的特征提取器即模型和参数拿来训练有预训练模型的时候尽量用预训练模型from torchvision.models import resnet18 #加载ImageNet预训练权重w比随机初始化收敛更快、精度更高 model resnet18(pretrained True)#把大佬训练好的w拿来用 #获得最后一层全连接的输入特征值 in_fetures model.fc.in_features#模型的维度 #替换最后一层全连接将1000分类改为11分类 model.fc nn.linear(in_fetures,11)六、训练和验证主函数1.交叉熵损失用来衡量预测的概率分布和真实标签有多像2.np.sum(np.argmax(pred.detach().cpu().numpy(), axis1) target.cpu().numpy())np.argmax():计算最大值下标axis1横轴[ [[0.1, 0.5, 0.4], 1 1 true[0.2, 0.3, 0.5], 2 0 false[0.2, 0.1, 0.7], 2 2 true] ]3.为什么要做无梯度计算计算梯度是为了训练模型不计算梯度视为了省资源、提速、不破坏模型。在训练时需要算梯度用来更新权重测试和部署时只需要输出结果。def train_val(model, train_loader, val_loader, no_label_loader, device, epochs, optimizer, loss, thres, save_path): #模型移到设备 model model.to(device) #半监督学习加载器初始为None semi_loader None #存储训练 plt_train_loss [] plt_val_loss [] #验证的loss和acc用于绘图 plt_train_acc [] plt_val_acc [] max_acc 0.0#最佳验证准确率用于保存最优模型 #遍历每个epoch for epoch in range(epochs): #初始化本轮的loss和acc train_loss 0.0 val_loss 0.0 train_acc 0.0 val_acc 0.0 semi_loss 0.0 semi_acc 0.0 start_time time.time()#记录本轮开始时间 #训练阶段 model.train()#模型设为训练模式启动dropout/bn等训练层 #遍历训练集 for batch_x, batch_y in train_loader: x, target batch_x.to(device), batch_y.to(device)#数据移到设备 pred model(x)#模型预测 train_bat_loss loss(pred, target)#计算损失交叉熵损失分类任务标配 train_bat_loss.backward()#反向传播计算梯度梯度回传 optimizer.step() #优化器更新权重 optimizer.zero_grad()# 更新参数 之后要梯度清零否则会累积梯度 train_loss train_bat_loss.cpu().item()#累加损失转为cpu值避免GPU内存占用 train_acc np.sum(np.argmax(pred.detach().cpu().numpy(), axis1) target.cpu().numpy())#计算准确率预测标签与真实标签对比求和 #计算本轮训练平均loss和acc plt_train_loss.append(train_loss / train_loader.__len__()) plt_train_acc.append(train_acc/train_loader.dataset.__len__()) #记录准确率 #如果有半监督数据训练半监督样本 if semi_loader! None: for batch_x, batch_y in semi_loader: x, target batch_x.to(device), batch_y.to(device) pred model(x) semi_bat_loss loss(pred, target) semi_bat_loss.backward() optimizer.step() # 更新参数 之后要梯度清零否则会累积梯度 optimizer.zero_grad() semi_loss semi_bat_loss.cpu().item()#累加半监督损失 semi_acc np.sum(np.argmax(pred.detach().cpu().numpy(), axis1) target.cpu().numpy())#累加半监督准确率 print(半监督数据集的训练准确率为, semi_acc/train_loader.dataset.__len__()) #----------------------------验证阶段---------------------------------- model.eval()#模型设为评估模式关闭dropout/bn更新 #无梯度计算 with torch.no_grad(): for batch_x, batch_y in val_loader: x, target batch_x.to(device), batch_y.to(device) pred model(x) val_bat_loss loss(pred, target) val_loss val_bat_loss.cpu().item() val_acc np.sum(np.argmax(pred.detach().cpu().numpy(), axis1) target.cpu().numpy()) plt_val_loss.append(val_loss / val_loader.__len__()) plt_val_acc.append(val_acc / val_loader.dataset.__len__()) #---------------------------------------------------------------------------- #生成半监督数据保存最优模型 #每3个epoch且验证准确率0.6时生成半监督数据 if epoch%3 0 and plt_val_acc[-1] 0.6: semi_loader get_semi_loader(no_label_loader, model, device, thres) #保存最优模型验证准确率最高时 if val_acc max_acc:#只有验证准确率超过之前的最大值时才保存避免保存差的模型 torch.save(model, save_path) max_acc val_acc #打印本轮训练信息 print([%03d/%03d] %2.2f sec(s) TrainLoss : %.6f | valLoss: %.6f Trainacc : %.6f | valacc: %.6f % \ (epoch, epochs, time.time() - start_time, plt_train_loss[-1], plt_val_loss[-1], plt_train_acc[-1], plt_val_acc[-1]) ) # 打印训练结果。 注意python语法 %2.2f 表示小数位为2的浮点数 后面可以对应。 #绘制loss曲线 plt.plot(plt_train_loss) plt.plot(plt_val_loss) plt.title(loss) plt.legend([train, val]) plt.show() #绘制acc曲线 plt.plot(plt_train_acc) plt.plot(plt_val_acc) plt.title(acc) plt.legend([train, val]) plt.show()如果训练loss下降但验证loss上升说明过拟合如果两者都下降说明收敛正常。七、主程序初始化启动训练#数据路径 #训练集文件路径 train_path rF:\pycharm\beike\classification\food_classification\food-11_sample\training\labeled #验证集文件路径 val_path rF:\pycharm\beike\classification\food_classification\food-11_sample\validation #无标签文件路径 no_label_path rF:\pycharm\beike\classification\food_classification\food-11_sample\training\unlabeled\00 #初始化数据集 train_set food_Dataset(train_path, train) val_set food_Dataset(val_path, val) no_label_set food_Dataset(no_label_path, semi) #构建DataLoader批处理洗牌多线程 train_loader DataLoader(train_set, batch_size16, shuffleTrue) val_loader DataLoader(val_set, batch_size16, shuffleTrue) no_label_loader DataLoader(no_label_set, batch_size16, shuffleFalse) #训练参数 lr 0.001#学习率 loss nn.CrossEntropyLoss()#损失函数分类任务 #优化器AdamX带权重衰减的Adam防止过拟合 optimizer torch.optim.AdamW(model.parameters(), lrlr, weight_decay1e-4) #设备优先GPU无则CPU device cuda if torch.cuda.is_available() else cpu #模型保存路径 save_path model_save/best_model.pth #训练轮次 epochs 15 #半监督学习置信度阈值 thres 0.99 #启动训练 train_val(model, train_loader, val_loader, no_label_loader, device, epochs, optimizer, loss, thres, save_path)

相关文章:

李哥深度学习班学习笔记——图像识别

一、导入依赖库​ import random #用于设置随机种子,保证实验可复现 import torch #Pytorh核心库,构建和训练神经网络 import torch.nn as nn #Pytorch神经网络层模块 import numpy as np #数值计算库,处理矩阵 import os #…...

Spring AI Alibaba学习记录(ChatModels篇)

目标:实现简单的聊天接口调用依赖配置(Maven)添加以下依赖:​ <dependencies> <!-- Spring AI Alibaba Agent Framework --><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-agent-framework</arti…...

SQL 客户端远程登录服务器详细操作教程

在日常开发和运维工作中&#xff0c;经常需要通过 SQL 客户端远程连接服务器上的 SQL Server 数据库&#xff0c;本文将详细讲解完整的配置和连接步骤&#xff0c;同时附上连接失败的排查方法&#xff0c;亲测有效&#xff0c;适合新手快速上手。一、服务器端 SQL Server 配置远…...

【备赛指南】2026全国大学生嵌入式大赛-ST赛道官方推荐,华清远见STM32U5/MP157开发板助你一臂之力!

第九届&#xff08;2026&#xff09;全国大学生嵌入式芯片与系统设计竞赛&#xff08;以下简称"大赛"&#xff09;已正式启动&#xff0c;报名火热进行中。作为教育部认证的国家级A类赛事&#xff0c;大赛历经九年积淀&#xff0c;已成为检验高校电子类专业人才培养质…...

vmd分解联合小波阈值降噪MATLAB代码。具体实现功能如下: 1.数据加载与预处理 数据从CSV文件读取并转换为数组,处理了多列数据的情况。 采样频率 Fs 设置为1000 Hz,这是后续时频分析的

vmd分解联合小波阈值降噪MATLAB代码。具体实现功能如下&#xff1a; 1.数据加载与预处理 数据从CSV文件读取并转换为数组&#xff0c;处理了多列数据的情况。 采样频率 Fs 设置为1000 Hz&#xff0c;这是后续时频分析的基础。 2.参数初始化 VMD分解参数&#xff08;如带宽约束 …...

分库分表(一)

假设目前有一张表order 订单表&#xff0c;需要分库分表&#xff0c;举例给出方案设计&#xff0c;并解决上述提到的分库分表带来的问题&#xff0c;详细说明下面给你用一个比较接近真实互联网生产环境的例子来说明&#xff1a; 假设有一张 order 订单表&#xff0c;数据量增长…...

京东社招——Java后端开发面试复盘

最近参加了京东大数据的面试&#xff0c;整个过程涵盖了项目细节、基础八股文以及手撕算法。本文将这次面试中遇到的9个核心问题进行了复盘和深度整理&#xff0c;特别是关于RabbitMQ的消息积压处理以及MySQL的RR隔离级别实现。base&#xff1a;北京1. 项目问题&#xff1a;你的…...

全自动颗粒清洁度分析系统,西恩士工业让颗粒计数精准高效

颗粒计数是清洁度检测的核心环节&#xff0c;传统的人工颗粒计数&#xff0c;不仅效率低&#xff0c;还容易出现误判、漏判&#xff0c;尤其是大规模生产时&#xff0c;人工计数根本跟不上节奏。西恩士的全自动颗粒清洁度分析系统&#xff0c;让颗粒计数摆脱人工&#xff0c;做…...

为什么要使用动态IP代理?详解动态IP在不同业务场景下的技术选型逻辑

做网络爬虫总被封IP&#xff1f;多账号运营动辄被风控警告&#xff1f;采集数据时地域限制拦路、数据不准&#xff1f;相信很多做技术、做运营的伙伴&#xff0c;在高频网络操作中&#xff0c;都曾被这些问题困住。为什么很多企业和从业者&#xff0c;都离不开动态IP代理&#…...

交稿前一晚!千笔,专科生论文救星!

你是否曾在论文写作中感到力不从心&#xff1f;选题无头绪、框架混乱、文献资料难找、查重率高得让人焦虑……这些难题&#xff0c;是否让你夜不能寐&#xff1f;专科生的论文之路&#xff0c;本就充满挑战&#xff0c;而千笔AI&#xff0c;正是为解决这些问题而生。它用智能技…...

实测有效:解决VSCode编译运行C++前无故卡顿的方案

最近用VSCode写C&#xff08;其实C也一样&#xff09;的时候发现了一个很闹心的问题&#xff1a;编译和运行本身速度没问题&#xff0c;但每次点执行后&#xff0c;VSCode会先卡好几秒才正式开始编译&#xff0c;加载圈完全是空转&#xff0c;白白浪费时间。踩了不少坑后终于找…...

求最大子序和---涉及到贪心+动态规划

1.什么是贪心和动态规划package siyangyuan;/*** Class Name :MaxSubArray* Package :siyangyuan* Description:** Author: Mr.chunxugao* Create: 2026-03-12- 14:13* Version:v1.0*///求最大子序和 public class MaxSubArray {public static int maxSubArray(int[] nums){//贪…...

2026全球范围内最知名且权威的计算机科技与人工智能信息获取平台

以下是全球范围内最知名且权威的计算机科技与人工智能信息获取平台&#xff0c;涵盖科技媒体、学术研究、开发者社区、AI工具导航以及趋势追踪平台等多个维度。一、国际权威科技媒体TechCrunch网址&#xff1a;https://techcrunch.com/硅谷科技风向标&#xff0c;长期关注科技创…...

基于PLC的药品包装机控制系统设计

收藏关注不迷路&#xff01;&#xff01; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff08;免费咨询指导选题&#xff09;&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;希望帮助更多…...

基于PLC的小型音乐喷泉设计

收藏关注不迷路&#xff01;&#xff01; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff08;免费咨询指导选题&#xff09;&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;希望帮助更多…...

如何从bode图得到单位阶跃的趋势

传递函数>阶跃响应&#xff1b;拉普拉斯逆变化就可以得到时域函数&#xff0c;可以绘制出图像。bode图>阶跃响应&#xff1b;以下例子进行测试&#xff1a;Ge -15.93 s---------------------s^2 16.34 s 94.09从伯德图&#xff08;Bode Plot&#xff09;定性判断单位阶…...

基于PLC的隧道照明控制系统设计

收藏关注不迷路&#xff01;&#xff01; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff08;免费咨询指导选题&#xff09;&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;希望帮助更多…...

期货软件开发「启动加载页 / 初始化窗口」

一、初始化窗口作用&#xff1a;• 程序刚打开时显示• 后台连接行情服务器• 加载历史 K 线 / 行情数据• 加载完成后自动进入主界面 二、当前已实现的核心功能1. 窗体基础功能• 无边框拖动&#xff08;顶部栏按住可移动窗口&#xff09;• 最小化按钮 •关闭按钮• 基于 …...

供应链产研交付提效:后端开发提效实战

引言 在传统后端开发流程中&#xff0c;需求解析、接口开发、测试验证、部署上线等环节存在大量重复性工作&#xff0c;且需求变更易导致研发成本上升、交付周期延长。为解决这一痛点&#xff0c;本文围绕后端开发提效展开全维度规划&#xff0c;从架构设计、分阶段落地计划、核…...

洛谷P8218 【深进1.例1】求区间和 考点:一维前缀和

题目 P8218 【深进1.例1】求区间和 - 洛谷 核心思路 一维前缀和模板题 代码 可以让AI总结一下代码逻辑 这段代码实现了一维前缀和算法&#xff0c;用于高效解决区间求和问题。主要逻辑如下&#xff1a; 预处理 (数据输入与求和)&#xff1a; 读取数组长度 n。在读取每个元…...

SGP.22 eSIM通信原理-打电话

三个关键阶段&#xff1a;准备阶段&#xff08;下载Profile&#xff09;、激活阶段&#xff08;网络注册&#xff09;和使用阶段&#xff08;拨打电话&#xff09;。 第一阶段&#xff1a;准备——将中国移动的“身份”下载到手机 用户买了一部支持eSIM的新手机&#xff0c;决定…...

Python自动化实现思路

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快Python自动化实现思路通常分为以下几步1. 确定自动化测试的范围和目标&#xff1a;首先需要明确需要进行自动化测试的范围和目标&#xff0c;包括测试场景、测试用…...

S款直流一体机模块问题排查指导

S款直流一体机模块问题排查指导一、问题现象&#xff1a;现场S款直流一体机设备启动时报错&#xff1a;绝缘检测超时&#xff0c;请插拔充电桩。或者事件内有模块的相关报错&#xff0c;比如&#xff1a;直流模块通讯故障&#xff0c;直流模块输出故障等。图一&#xff1a;启动…...

双有源桥式DC-DC变换器仿真及Matlab建模实践:自行设定输入输出电压值与基础讲解

双有源桥式dcdc变换器仿真 dab变换器Matlab仿真模型 自行设计输入输出电压值 配基础讲解一份双有主动桥&#xff08;DAB&#xff09;变换器这个拓扑结构就像两个武林高手在推手——输入侧的H桥和输出侧的H桥通过高频变压器连接&#xff0c;通过调节两者的相位差来控制能量流动。…...

CGAL ::Surface Mesh 参考文档examples详解

1 引言 CGAL::Surface_mesh 是 CGAL 中用于表示多面体表面的半边数据结构&#xff08;Halfedge Data Structure, HDS&#xff09;&#xff0c;是传统指针式半边结构和3D 多面体表面的轻量化替代方案&#xff0c;核心优势是基于整数索引而非指针&#xff0c;兼顾内存效率、易用…...

膜结构车棚性价比排名深度解析

在停车设施领域&#xff0c;膜结构车棚凭借其独特优势逐渐成为热门选择。下面将深入分析膜结构车棚性价比相关因素。性能优势凸显性价比膜结构车棚以高强度建筑膜材为覆盖材料&#xff0c;配合钢结构支撑。其膜材有 PVC/PVDF 涂层聚酯膜、PTFE 膜等。它具有诸多性能优势&#x…...

实验室纯水机怎么选?2026 纯水系统品牌及选型全攻略

在实验室筹建或设备更新时&#xff0c;面对琳琅满目的品牌和参数&#xff0c;“怎么选”往往比“买不买”更令人头疼。选错设备&#xff0c;轻则耗材成本高昂&#xff0c;重则导致实验结果偏差、质谱基线不稳。要选对实验室纯水机&#xff0c;建议按照以下“四步筛选法”进行决…...

(新界面)NVR即时回放功能操作指导

&#xff08;新界面&#xff09;NVR即时回放功能操作指导一、功能介绍对系统当前时间点之前5分钟&#xff08;可自定义&#xff0c;默认5分钟&#xff09;内的录像进行回放&#xff0c;方便在预览实况时发现异常并即时回放。旧版本NVR需升级至NVR-BXXXX.50.13.250529或更高版本…...

技术人的困境:参数碾压对手,客户却不选你?用“技术路线图叙事”破局

作为技术出身的B2B从业者&#xff0c;你可能一直坚信&#xff1a;技术够硬&#xff0c;就是最好的销售语言。你带着PPT去见客户&#xff0c;第一页&#xff1a;屈服强度对比图&#xff0c;比竞争对手高15%&#xff1b;第二页&#xff1a;专利清单&#xff0c;密密麻麻排了三页&…...

求推荐超绝高性价比的GEO优化公司

一直以来&#xff0c;传统SEO投放大量网络资源却难以让用户精准找到品牌&#xff0c;且严重依赖搜索框、时效慢、流量少等问题&#xff0c;是当前行业普遍面临的难题。倍霖卓越推出的倍霖GEO针对这一问题提供了专业解决方案。倍霖GEO系统&#xff0c;采用多类型多平台全方位内容…...