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

制作网页的模板的网站帮别人做设计图的网站

制作网页的模板的网站,帮别人做设计图的网站,县级网站建设培训会,海外域名怎么打开在这篇文章#xff1a;【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割2#xff08;基础数据流篇#xff09; 的最后#xff0c;我们提到了#xff1a; 在采用vent模型进行3d数据的分割训练任务中#xff0c;输入大小是16*96*96#xff0c;这个的裁剪是放到Dataset类…在这篇文章【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割2基础数据流篇 的最后我们提到了 在采用vent模型进行3d数据的分割训练任务中输入大小是16*96*96这个的裁剪是放到Dataset类里面裁剪下来的image和mask。但是在训练时候发现几个问题 加载数据耗费了很长时间从启动训练到正式打印开始按batch循环这段时间就有30分钟batch64, torch.utils.data.DataLoader里面的num_workers8训练总是到8的倍数时候要停顿较长时间等待4个GPU并行训练的GPU的利用率长时间为0偶尔会升上去一瞬间又为0free -m查看的内存占用发现buff和cache会逐步飙升慢慢接近占满。 请问出现这种情况会是哪里存在问题啊模型是正常训练和收敛拟合的也比较好就是太慢了。分析myDataset数据读取的代码有几个地方可能是较为耗时和占用内存的地方 getAnnotations 函数需要从csv文件中获取文件名和结节对应坐标最后存储为一个字典这个是始终要占着内存空间的getNpyFile_Path 函数dataFile_paths和labelFile_paths都需要调用有些重复了这部分的占用是可以降低一倍的get_annos_label 函数也是一样的问题有些重复了这部分的占用是可以降低一倍的。 上面这几个函数都是在类的__init__阶段就完成的这种多次的循环可能是在开始batch循环前这部分时间耗费时间的主要原因其次由于重复占用内存进一步加剧了性能降低使得后续的训练变的比较慢。 为了解决上面的这些问题产生了本文2.0 的Dataset数据加载的版本其最大的改动就是将原本从csv文件获取结节坐标的形式改为从npy文件中获取。这样image、mask、Bbox都是一一对应的单个文件了。从后续的实际训练发现也确实是如此解决了这个耗时的问题让训练变的很快。 所以只要我们将牟定的值进行精简减少__init__阶段的内存占用这个问题就应该可以完美解决了。所以本篇就是遵照这个原则尽量的在数据预处理阶段就把能不要的就丢弃只留下最简单的一一结构。将预处理前置避免在构建数据阶段调用。 LUNA16数据的预处理可以参照这里本篇就是通过这里方式产生的数据如下 【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割6数据预处理【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割7数据预处理【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割8CT肺实质分割【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割9patch 的 crop 和 merge 操作 一、搭设数据流框架 在pytorch中构建训练用的数据流都遵循下面这样一个结构。其中主要的思路是这样的 在__init__中是类初始化阶段就执行的。在这里需要牟定某个值将训练需要的内容都获取到但尽量少的占用内容和花费时间在__getitem__中会根据__init__牟定的那个值获取到一个图像和标签信息读取和增强等等操作最后返回Tensor值__len__返回的是一个epoch训练牟定值的长度。 下面就是一个简易的框架结构留作参考后续的构建数据流都可以对这里补充。 class myDataset_v3(Dataset):def __init__(self, data_dir, isTrainTrue):self.data []if isTrain:self.data ···elseself.data ···def __len__(self):return len(self.data)def __getitem__(self, index):# ********** get file dir **********image, label self.data[index] # get whole data for one subject# ********** change data type from numpy to torch.Tensor **********image torch.from_numpy(image).float() label torch.from_numpy(label).float() return image, label在这篇文章中对这个类里面的参数进行了详细的介绍感兴趣的可以直达去学习【BraTS】Brain Tumor Segmentation 脑部肿瘤分割3构建数据流 二、完善框架内容 相信通过前面6、7、8、9四篇博客的介绍你已经将Luna16的原始数据集处理成了一一对应的我们训练所需要的数据形式包括 _bboxes.npy记录了结节中心点的坐标和半径_clean.nrrdCT原始图像数组_mask.nrrd标注文件mask数组和_clean.nrrd的shape一样 还包括一些其他的.npy记录的都是整个变换阶段的一些量在训练阶段是使用不到的这里就不展开了。最最关注的就是上面三个文件并且是根据seriesUID一一对应的。 如果是这样的数据情况下我们构建myDataset_v3(Dataset)数据量思考在__init__阶段可以以哪个为锚点尽量少占用内存的情况下将所需要的图像、标注信息都可以在__getitem__阶段依次获取到呢 那就是seriesUID的文件名。他是可以一拖三的并且一个列表就可以了这样是最节省内存的方式。于是我们在__init__阶段的定义如下 class myDataset_v3(Dataset):def __init__(self, data_dir, crop_size(16, 96, 96), isTrainFalse):self.bboxesFile_path []for file in os.listdir(data_dir):if _bboxes.npy in file:self.bboxesFile_path.append(os.path.join(data_dir, file))self.crop_size crop_sizeself.crop_size_z, self.crop_size_h, self.crop_size_w crop_sizeself.isTrain isTrain然后在__len__的定义就自然而然的知道了如下 def __len__(self):return len(self.bboxesFile_path)最为重要且最难的也就是__getitem__的定义在这里需要做一下几件事情 获取各个文件的路径获取文件对应的数据裁剪出目标patch数组转成Tensor。 然后在定义__getitem__中就发现了问题如下 def __getitem__(self, index):bbox_path self.bboxesFile_path[index]img_path bbox_path.replace(_bboxes.npy, _clean.nrrd)label_path bbox_path.replace(_bboxes.npy, _mask.nrrd)img, img_shape self.load_img(img_path)label self.load_mask(label_path)zyx_centerCoor self.getBboxes(bbox_path)def getBboxes(self, bboxFile_path):bboxes_array np.load(bboxFile_path, allow_pickleTrue)bboxes_list bboxes_array.tolist()xyz_list [[zyx[0], zyx[2], zyx[1]] for zyx in bboxes_list]return random.choice(xyz_list)主要是因为一个_bboxes.npy记录的结节坐标点并不只有一个结节。如果将获取bbox的放到__getitem__就会发现他一次只能裁剪出一个patch就不可能对多个结节的情况都处理到。所以我这里采用了random.choice的方式随机的选择一个结节。 但是这种方式是不好的因为他会降低结节在学习过程中出现的次数尽管是随机的但是相当于某些类型的数据量变少了。同样学习的epoch次数下那些只有一个结节的就被学习的次数相对变多了。 为了解决这个问题直接将结节数与文件名一一对应起来这样对于每一个结节来说机会都是均等的了。代码如下所示 import os import random import numpy as np import matplotlib.pyplot as plt from tqdm import tqdm import torch from torch.utils.data import Dataset import nrrd import cv2class myDataset_v3(Dataset):def __init__(self, data_dir, crop_size(16, 96, 96), isTrainFalse):self.dataFile_path_bboxes []for file in os.listdir(data_dir):if _bboxes.npy in file:one_path_bbox_list self.getBboxes(os.path.join(data_dir, file))self.dataFile_path_bboxes.extend(one_path_bbox_list)self.crop_size crop_sizeself.crop_size_z, self.crop_size_h, self.crop_size_w crop_sizeself.isTrain isTraindef __getitem__(self, index):bbox_path, zyx_centerCoor self.dataFile_path_bboxes[index]img_path bbox_path.replace(_bboxes.npy, _clean.nrrd)label_path bbox_path.replace(_bboxes.npy, _mask.nrrd)img, img_shape self.load_img(img_path)# print(img_shape:, img_shape)label self.load_mask(label_path)# print(zyx_centerCoor:, zyx_centerCoor)cutMin_list self.getCenterScope(img_shape, zyx_centerCoor)if self.isTrain:rd random.random()if rd 0.5:cut_list [cutMin_list[0], cutMin_list[0]self.crop_size_z, cutMin_list[1], cutMin_list[1]self.crop_size_h, cutMin_list[2], cutMin_list[2]self.crop_size_w] ### z,y,xstart1, start2, start3 self.random_crop_around_nodule(img_shape, cut_list, crop_sizeself.crop_size, leftTop_ratio0.3)elif rd 0.1:start1, start2, start3 self.random_crop_negative_nodule(img_shape, crop_sizeself.crop_size)else:start1, start2, start3 cutMin_listelse:start1, start2, start3 cutMin_listimg_crop img[start1:start1 self.crop_size_z, start2:start2 self.crop_size_h,start3:start3 self.crop_size_w]label_crop label[start1:start1 self.crop_size_z, start2:start2 self.crop_size_h,start3:start3 self.crop_size_w]# print(before:, img_crop.shape, label_crop.shape)# 计算需要pad的大小if img_crop.shape ! self.crop_size:pad_width [(0, self.crop_size_z-img_crop.shape[0]), (0, self.crop_size_h-img_crop.shape[1]), (0, self.crop_size_w-img_crop.shape[2])]img_crop np.pad(img_crop, pad_width, modeconstant, constant_values0)if label_crop.shape ! self.crop_size:pad_width [(0, self.crop_size_z-label_crop.shape[0]), (0, self.crop_size_h-label_crop.shape[1]), (0, self.crop_size_w-label_crop.shape[2])]label_crop np.pad(label_crop, pad_width, modeconstant, constant_values0)# print(after:, img_crop.shape, label_crop.shape)img_crop np.expand_dims(img_crop, 0) # (1, 16, 96, 96)img_crop torch.from_numpy(img_crop).float()label_crop torch.from_numpy(label_crop).long() # (16, 96, 96) label不用升通道维度return img_crop, label_cropdef __len__(self):return len(self.dataFile_path_bboxes)def load_img(self, path_to_img):if path_to_img.startswith(LKDS):img np.load(path_to_img)else:img, _ nrrd.read(path_to_img)img img.transpose((0, 2, 1)) # 与xyz坐标变换对应return img/255.0, img.shapedef load_mask(self, path_to_mask):mask, _ nrrd.read(path_to_mask)mask[mask1] 1mask mask.transpose((0, 2, 1)) # 与xyz坐标变换对应return maskdef getBboxes(self, bboxFile_path):bboxes_array np.load(bboxFile_path, allow_pickleTrue)bboxes_list bboxes_array.tolist()one_path_bbox_list []for zyx in bboxes_list:xyz [zyx[0], zyx[2], zyx[1]]one_path_bbox_list.append([bboxFile_path, xyz])return one_path_bbox_listdef getCenterScope0(self, img_shape, zyx_centerCoor):cut_list [] # 切割需要用的数for i in range(len(img_shape)): # 0, 1, 2 → z,y,xif i 0: # za zyx_centerCoor[-i - 1] - self.crop_size_z/2 # zb zyx_centerCoor[-i - 1] self.crop_size_z/2 # y,zelse: # y, xa zyx_centerCoor[-i - 1] - self.crop_size_w/2b zyx_centerCoor[-i - 1] self.crop_size_w/2# 超出图像边界 1if a 0:a self.crop_size_zb self.crop_size_w# 超出边界 2elif b img_shape[i]:if i 0:a img_shape[i] - self.crop_size_zb img_shape[i]else:a img_shape[i] - self.crop_size_wb img_shape[i]else:passcut_list.append(int(a))cut_list.append(int(b))return cut_listdef getCenterScope(self, img_shape, zyx_centerCoor):img_z, img_y, img_x img_shapezc, yc, xc zyx_centerCoorzmin max(0, zc - self.crop_size_z // 3)ymin max(0, yc - self.crop_size_h // 2)xmin max(0, xc - self.crop_size_w // 2)cutMin_list [int(zmin), int(ymin), int(xmin)]return cutMin_listdef random_crop_around_nodule(self, img_shape, cut_list, crop_size(16, 96, 96), leftTop_ratio0.3)::param img::param label::param center::param radius::param cut_list::param crop_size::param leftTop_ratio: 越大阴性样本越多(需要考虑crop_size):return:img_z, img_y, img_x img_shapecrop_z, crop_y, crop_x crop_sizez_min, z_max, y_min, y_max, x_min, x_max cut_list# print(z_min, z_max, y_min, y_max, x_min, x_max:, z_min, z_max, y_min, y_max, x_min, x_max)z_min max(0, int(z_min-crop_z*leftTop_ratio))z_max min(img_z, int(z_min crop_z*leftTop_ratio))y_min max(0, int(y_min-crop_y*leftTop_ratio))y_max min(img_y, int(y_mincrop_y*leftTop_ratio))x_min max(0, int(x_min-crop_x*leftTop_ratio))x_max min(img_x, int(x_mincrop_x*leftTop_ratio))z_start random.randint(z_min, z_max)y_start random.randint(y_min, y_max)x_start random.randint(x_min, x_max)return z_start, y_start, x_startdef random_crop_negative_nodule(self, img_shape, crop_size(16, 96, 96), boundary_ratio0.5):img_z, img_y, img_x img_shapecrop_z, crop_y, crop_x crop_sizez_min 0#crop_z*boundary_ratioz_max img_z-crop_z#img_z - crop_z*boundary_ratioy_min 0#crop_y*boundary_ratioy_max img_y-crop_y#img_y - crop_y*boundary_ratiox_min 0#crop_x*boundary_ratiox_max img_x-crop_x#img_x - crop_x*boundary_ratioz_start random.randint(z_min, z_max)y_start random.randint(y_min, y_max)x_start random.randint(x_min, x_max)return z_start, y_start, x_start上述就是本次改写后新的数据流完整代码没有加入数据增强的操作。在训练时引入了三种多样性 确保mask有结节目标的情况下随机的变换结节在patch中的位置全图随机的进行裁剪主要是产生负样本直接使用结节为中心点的方式进行裁剪。 这样做的目的其实是考虑到结节在patch中的位置可能会影响到最终的预测。因为最后我们在使用的推理阶段其实是不知道结节在图像中的哪个位置的只能遍历所有的patch然后再将预测的结果拼接成一个完整的mask进而对mask的处理知道了所有结节的位置。 这就要求结节无论是出现在图像中的任何位置都需要找到他并且尽量少的假阳性。 这块是很少看到论文涉及到的内容我不清楚是不是论文只关于了指标而忘记了假阳性这样一个附加产物。还有就是这些patch的获取方式是预先裁剪下来直接读取patch数组的形式进行训练的。这种也不好多样性不够还比较的麻烦。 这一小节还要讲的就是getCenterScope和random_crop_around_nodule两个函数。getCenterScope中为什么整除3是因为多次查看总结出来的。如果是整除2就发现所有的结节都偏下这点的原因还没有想明白。知道的求留言。 如果是一个二维的平面已知中心点那么找到左上角的最小值那就应该是中心点坐标减去二分之一的宽高。但是在z轴也采用减去二分之一的发现所有裁剪出来的结节就很靠下。 所以这里采用了减去三分之一让他在z轴上往上移动了一点。这里的疑问还没有搞明白知道的评论区求指教。 random_crop_around_nodule是控制了裁剪左上角最小值和最大值的坐标在这个区间内随机的确定进而使得结节的裁剪更加的多样性。如下图所示 我只要想让每一次的裁剪都有结节在只需要结节左上角的坐标落在一定的区间内即可。leftTop_ratio参数就是用于控制左上角的点远离左上角的距离。 这个值需要自己根据patch的大小自己决定多次查看很重要。 三、验证数据流 构建好数据量的类函数还不能算完。因为你不知道此时的数据流是不是符合你要求的。所以如果能够模拟训练过程提前看看每一个patch的结果那就再好不过了。 本章节就是这个目的我们把图像和mask通通打出来看看这样就知道是否存在问题了。查看的方法也比较的简单可以抄过去用到之后自己的项目里。 def getContours(output):img_seged output.numpy().astype(np.uint8)img_seged img_seged * 255# ---- Predict bounding box results with txt ----kernel np.ones((5, 5), np.uint8)img_seged cv2.dilate(img_seged, kernelkernel)_, img_seged_p cv2.threshold(img_seged, 127, 255, cv2.THRESH_BINARY)try:_, contours, _ cv2.findContours(np.uint8(img_seged_p), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)except:contours, _ cv2.findContours(np.uint8(img_seged_p), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)return contoursif __name____main__:data_dir r./validdataset_valid myDataset_v3(data_dir, crop_size(48, 96, 96), isTrainFalse) # 送入datasetvalid_loader torch.utils.data.DataLoader(dataset_valid, # 生成dataloaderbatch_size1, shuffleFalse,num_workers0) # 16) # 警告页面文件太小时可改为0print(valid_dataloader_ok)print(len(valid_loader))for batch_index, (data, target) in tqdm(enumerate(valid_loader)):name dataset_valid.dataFile_path_bboxes[batch_index]print(name:, name)print(image size ......)print(data.shape) # torch.Size([batch, 1, 16, 96, 96])print(label size ......)print(target.shape) # torch.Size([2])# 按着batch进行显示for i in range(data.shape[0]):onePatch data[i, 0, :, :]onePatch_target target[0, :, :, :]print(one_patch:, onePatch.shape, np.max(onePatch.numpy()), np.min(onePatch.numpy()))fig, ax plt.subplots(6, 8, figsize[14, 16])for i in range(6):for j in range(8):one_pic onePatch[i * 4 j]img one_pic.numpy()*255.0# print(one_pic img:, one_pic.shape, np.max(one_pic.numpy()), np.min(one_pic.numpy()))one_mask onePatch_target[i * 4 j]contours getContours(one_mask)for contour in contours:x, y, w, h cv2.boundingRect(contour)xmin, ymin, xmax, ymax x, y, x w, y h# print(contouts:, xmin, ymin, xmax, ymax)cv2.drawContours(img, contour, -1, (0, 0, 255), 2)# cv2.rectangle(img, (int(xmin), int(ymin)), (int(xmax), int(ymax)), (0, 0, 255),# thickness1)ax[i, j].imshow(img, cmapgray)ax[i, j].axis(off)# print(one_target:, onePatch.shape, np.max(onePatch.numpy()), np.min(onePatch.numpy()))fig, ax plt.subplots(6, 8, figsize[14, 16])for i in range(6):for j in range(8):one_pic onePatch_target[i * 4 j]# print(one_pic mask:, one_pic.shape, np.max(one_pic.numpy()), np.min(one_pic.numpy()))ax[i, j].imshow(one_pic, cmapgray)ax[i, j].axis(off)plt.show()显示出来的图像如下所示 你可以多看几张看的多了也就顺便给验证了结节裁剪的是否有问题。同时也可以采用训练模型看看在训练情况下阳性带结节的样本和全是黑色的没有结节的样本占到多少。这也为我们改上面的代码提供了参考标准。 四、总结 本文其实是对前面博客数据流问题的一个总结和找到解决问题的方法了。同时将一个验证数据量的过程给展示了出来方便我们后续更多的其他任务都是很有好处的。 如果你是一名初学者我相信该收获满满。如果你是奔着项目来的那肯定也找到了思路。数据集的差异主要体现在前处理上而到了训练阶段本篇可以帮助你快速的动手。 最后留下你的点赞和收藏。如果有问题欢迎评论和私信。后续会将训练和验证的代码进行介绍这部分同样是重点。
http://www.dnsts.com.cn/news/92345.html

相关文章:

  • seo 网站标题字数VPS wordpress 教程
  • 网站开发一般用哪些语言郑州网页网站制作
  • 建设企业学习网站河北城乡和住房建设厅官方网站
  • 美团网站网站建设发展广州网站排名优化报价
  • 坪山模板网站建设公司环保企业网站建设现状
  • 网站建设流程多少钱wordpress google收录
  • 建立本地网站网站开发开发需求文档模板
  • 网站服务器查询加盟项目
  • 滨海做网站公司南通住房和城乡建设厅网站首页
  • 网站建设程序编制金华手机建站模板
  • 织梦医院网站开发乐华网络公司联系方式
  • php网站开发工程师招聘要求1688做网站多少钱
  • 中国建造师官方网站华亭网站建设
  • 特产网站建设的目的家居商城网站模板
  • 网站经营中装建设集团网站
  • 网站和域名区别吗禅城网站制作
  • 网站建设控制如何创造一个网站
  • 家禽养殖公司网站怎么做wordpress的友情链设置
  • 旅游网站的建设的意义网页美工设计流程为
  • 库尔勒网站建设推广黑色wordpress主题
  • 设计网站 问题做网站主页图片一般多少m
  • 定州网站建设电话腾讯云 配置wordpress
  • 苏州网络公司建网站南昌做网站的
  • 曲靖网站推广沈阳招聘网官网
  • 快刷网站跨境电商多平台运营
  • 荣盛科技网站建设网站开发写好了怎么发布
  • 常德网站制作公司多少钱wordpress 企业主页
  • 南昌建设厅网站微信网站设计价格
  • 横山专业做网站建设的公司苏州建筑工程集团有限公司
  • 做微博分析的网站淘宝网淘我喜欢