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

湖南雷锋建设有限公司网站电商网站页面布局

湖南雷锋建设有限公司网站,电商网站页面布局,温州在线制作网站,江门关键词排名工具人类并不是完美的#xff0c;我们经常在编写软件的时候犯错误。有时这些错误很容易找到#xff1a;你的代码根本不工作#xff0c;你的应用程序会崩溃。但有些 bug 是隐藏的#xff0c;很难发现#xff0c;这使它们更加危险。在处理深度学习问题时#xff0c;由于某些不确…人类并不是完美的我们经常在编写软件的时候犯错误。有时这些错误很容易找到你的代码根本不工作你的应用程序会崩溃。但有些 bug 是隐藏的很难发现这使它们更加危险。在处理深度学习问题时由于某些不确定性很容易产生此类错误很容易看到 web 应用的端点路由请求是否正确但却不容易检查梯度下降步骤是否正确。然而在深度学习实践例程中有很多 bug 是可以避免的。我想和大家分享一下我在过去两年的计算机视觉工作中所发现或产生的错误的一些经验。我在会议上谈到过这个话题很多人在会后告诉我「是的老兄我也有很多这样的 bug。」我希望我的文章能帮助你避免其中的一些问题。1.翻转图像和关键点假设有人在研究关键点检测问题。它们的数据看起来像一对图像和一系列关键点元组例如 [(0,1),(2,2)]其中每个关键点是一对 x 和 y 坐标。让我们对这些数据编进行基本的增强def flip_img_and_keypoints(img: np.ndarray, kpts:Sequence[Sequence[int]]):img np.fliplr(img)h, w, *_ img.shapekpts [(y, w - x) for y, x in kpts]return img, kpts上面的代码看起来很对是不是接下来让我们对它进行可视化。image np.ones((10, 10), dtypenp.float32)kpts [(0, 1), (2, 2)]image_flipped, kpts_flipped flip_img_and_keypoints(image, kpts)img1 image.copy()for y, x in kpts:img1[y, x] 0img2 image_flipped.copy()for y, x in kpts_flipped:img2[y, x] 0_ plt.imshow(np.hstack((img1, img2)))这个图是不对称的看起来很奇怪如果我们检查极值呢image np.ones((10, 10), dtypenp.float32)kpts [(0, 0), (1, 1)]image_flipped, kpts_flipped flip_img_and_keypoints(image, kpts)img1 image.copy()for y, x in kpts:img1[y, x] 0img2 image_flipped.copy()for y, x in kpts_flipped:img2[y, x] 0-------------------------------------------------------------------- -------IndexErrorTraceback (most recent call last)in8 img2 image_flipped.copy()9 for y, x in kpts_flipped:--- 10 img2[y, x] 0IndexError: index 10 is out of bounds for axis 1 with size 10不好这是一个典型的错误。正确的代码如下def flip_img_and_keypoints(img: np.ndarray, kpts: Sequence[Sequence[int]]):img np.fliplr(img)h, w, *_ img.shapekpts [(y, w - x - 1) for y, x in kpts]return img, kpts我们已经通过可视化检测到这个问题但是使用 x0 点的单元测试也会有帮助。一个有趣的事实是我们团队三个人(包括我自己)各自独立地犯了几乎相同的错误。2.继续谈谈关键点即使上述函数已修复也存在危险。接下来更多的是关于语义而不仅仅是一段代码。假设一个人需要用两只手掌来增强图像。看起来很安全——手在左右翻转后会还是手。但是等等我们对关键点语义一无所知。如果关键点真的是这样的意思呢kpts [(20, 20), # left pinky(20, 200), # right pinky...]这意味着增强实际上改变了语义left 变为 rightright 变为 left但是我们不交换数组中的 keypoints 索引。它会给训练带来巨大的噪音和更糟糕的指标。这里应该吸取教训在应用增强或其他特性之前了解并考虑数据结构和语义保持你的实验的独立性添加一个小的变化(例如一个新的转换)检查它是如何进行的如果分数提高了再合并。3.自定义损失函数熟悉语义分割问题的人可能知道 IoU (intersection over union)度量。不幸的是我们不能直接用 SGD 来优化它所以一个常见的技巧是用可微损失函数来逼近它。让我们编写相关代码def iou_continuous_loss(y_pred, y_true):eps 1e-6def _sum(x):return x.sum(-1).sum(-1)numerator (_sum(y_true * y_pred) eps)denominator (_sum(y_true ** 2) _sum(y_pred ** 2) -_sum(y_true * y_pred) eps)return (numerator / denominator).mean()看起来很不错让我们做一个小小的检查In [3]: ones np.ones((1, 3, 10, 10))...: x1 iou_continuous_loss(ones * 0.01, ones)...: x2 iou_continuous_loss(ones * 0.99, ones)In [4]: x1, x2Out[4]: (0.010099999897990103, 0.9998990001020204)在 x1 中我们计算了与标准答案完全不同的损失x2 是非常接近标准答案的函数的结果。我们预计 x1 会很大因为预测结果并不好x2 应该接近于零。这其中发生了什么上面的函数是度量的一个很好的近似。度量不是损失它通常越高越好。因为我们要用 SGD 把损失降到最低我们真的应该采用用相反的方法v def iou_continuous(y_pred, y_true):eps 1e-6def _sum(x):return x.sum(-1).sum(-1)numerator (_sum(y_true * y_pred) eps)denominator (_sum(y_true ** 2) _sum(y_pred ** 2)- _sum(y_true * y_pred) eps)return (numerator / denominator).mean()def iou_continuous_loss(y_pred, y_true):return 1 - iou_continuous(y_pred, y_true)这些问题可以通过两种方式确定编写一个单元测试来检查损失的方向形式化地表示一个期望即更接近实际的东西应该输出更低的损失做一个全面的检查尝试过拟合你的模型的 batch。4.使用 Pytorch假设一个人有一个预先训练好的模型并且是一个时序模型。我们基于 ceevee api 编写预测类。from ceevee.base import AbstractPredictorclass MySuperPredictor(AbstractPredictor):def __init__(self, weights_path: str, ):super().__init__()self.model self._load_model(weights_pathweights_path)def process(self, x, *kw):with torch.no_grad():res self.model(x)return resstaticmethoddef _load_model(weights_path):model ModelClass()weights torch.load(weights_path, map_locationcpu)model.load_state_dict(weights)return model这个密码正确吗也许吧对某些模型来说确实是正确的。例如当模型没有规范层时例如 torch.nn.BatchNorm2d或者当模型需要为每个图像使用实际的 norm 统计信息时(例如许多基于 pix2pix 的架构需要它)。但是对于大多数计算机视觉应用程序来说代码遗漏了一些重要的东西切换到评估模式。如果试图将动态 pytorch 图转换为静态 pytorch 图则很容易识别此问题。有一个 torch.jit 模块是用于这种转换的。一个简单的修复In [4]: model nn.Sequential(...: nn.Linear(10, 10),..: nn.Dropout(.5)...: )...:...: traced_model torch.jit.trace(model.eval(), torch.rand(10))# No more warnings!此时torch.jit.trace 多次运行模型并比较结果。这里看起来似乎没有区别。然而这里的 torch.jit.trace 不是万能的。这是一种应该知道并记住的细微差别。5.复制粘贴问题很多东西都是成对存在的训练和验证、宽度和高度、纬度和经度……如果仔细阅读你可以很容易地发现由一对成员之间的复制粘贴引起的错误v def make_dataloaders(train_cfg, val_cfg, batch_size):train Dataset.from_config(train_cfg)val Dataset.from_config(val_cfg)shared_params {batch_size: batch_size, shuffle: True,num_workers: cpu_count()}train DataLoader(train, **shared_params)val DataLoader(train, **shared_params)return train, val不仅仅是我犯了愚蠢的错误。在流行库中也有类似的错误。#https://github.com/albu/albumentations/blob/0.3.0/albumentations/aug mentations/transforms.pydef apply_to_keypoint(self, keypoint, crop_height0, crop_width0, h_start0, w_start 0, rows0, cols0, **params):keypoint F.keypoint_random_crop(keypoint, crop_height, crop_width, h_start, w_start, rows, cols)scale_x self.width / crop_heightscale_y self.height / crop_heightkeypoint F.keypoint_scale(keypoint, scale_x, scale_y) return keypoint别担心这个错误已经修复了。如何避免不要复制粘贴代码尽量以不要以复制粘贴的方式进行编码。datasets []data_a get_dataset(MyDataset(config[dataset_a]), config[shared_param], param_a) datasets.append(data_a)data_b get_dataset(MyDataset(config[dataset_b]), config[shared_param], param_b) datasets.append(data_b)datasets []for name, param in zip((dataset_a, dataset_b), (param_a, param_b), ):datasets.append(get_dataset(MyDataset(config[name]), config[shared_param], param))6.合适的数据类型让我们再做一个增强def add_noise(img: np.ndarray) - np.ndarray:mask np.random.rand(*img.shape) .5img img.astype(float32) * maskreturn img.astype(uint8)图像已经改变了。这是我们期望的吗嗯也许改变太多了。这里有一个危险的操作将 float32 转到 uint8。这可能导致溢出def add_noise(img: np.ndarray) - np.ndarray:mask np.random.rand(*img.shape) .5img img.astype(float32) * maskreturn np.clip(img, 0, 255).astype(uint8)img add_noise(cv2.imread(two_hands.jpg)[:, :, ::-1]) _ plt.imshow(img)看起来好多了是吧顺便说一句还有一个方法可以避免这个问题不要重新发明轮子可以在前人的基础上修改代码。例如albumentations.augmentations.transforms.GaussNoise 。我又产生了同样来源的 bug。这里出了什么问题首先使用三次插值调整 mask 的大小是个坏主意。将 float32 转换为 uint8 也存在同样的问题三次插值可以输出大于输入的值并导致溢出。我发现了这个问题。在你的循环里面有断言也是一个好主意。7.打字错误假设需要对全卷积网络(如语义分割问题)和一幅巨大的图像进行处理。图像太大了你没有机会把它放进你的 gpu 中——例如它可以是一个医学或卫星图像。在这种情况下可以将图像分割成一个网格独立地对每一块进行推理最后合并。另外一些预测交集可以用来平滑边界附近的伪影。我们来编码吧from tqdm import tqdmclass GridPredictor: This class can be used to predict a segmentation mask for the big image when you have GPU memory limitation def __init__(self, predictor: AbstractPredictor, size: int, stride: Optional[int] None): self.predictor predictorself.size sizeself.stride stride if stride is not None else size // 2def __call__(self, x: np.ndarray):h, w, _ x.shapemask np.zeros((h, w, 1), dtypefloat32)weights mask.copy()for i in tqdm(range(0, h - 1, self.stride)):for j in range(0, w - 1, self.stride):a, b, c, d i, min(h, i self.size), j, min(w, j self.size)patch x[a:b, c:d, :]mask[a:b, c:d, :] np.expand_dims(self.predictor(patch), -1) weights[a:b, c:d, :] 1return mask / weights有一个符号输入错误代码片段足够大因此可以很容易地找到它。我怀疑仅仅通过代码就可以快速识别它很容易检查代码是否正确class Model(nn.Module):def forward(self, x):return x.mean(axis-1)model Model()grid_predictor GridPredictor(model, size128, stride64)simple_pred np.expand_dims(model(img), -1)grid_pred grid_predictor(img)np.testing.assert_allclose(simple_pred, grid_pred, atol.001)调用方法的正确版本如下def __call__(self, x: np.ndarray):h, w, _ x.shapemask np.zeros((h, w, 1), dtypefloat32)weights mask.copy()for i in tqdm(range(0, h - 1, self.stride)):for j in range(0, w - 1, self.stride): a, b, c, d i, min(h, i self.size), j, min(w, j self.size)patch x[a:b, c:d, :]mask[a:b, c:d, :] np.expand_dims(self.predictor(patch), -1)weights[a:b, c:d, :] 1return mask / weights如果你仍然没有看出问题所在请注意线宽 [a:bc:d]1。8.ImageNet 规范化当一个人需要进行迁移学习时通常最好像训练 ImageNet 时那样对图像进行标准化。让我们使用我们已经熟悉的 albumentations 库。from albumentations import Normalizenorm Normalize()img cv2.imread(img_small.jpg)mask cv2.imread(mask_small.png, cv2.IMREAD_GRAYSCALE)mask np.expand_dims(mask, -1) # shape (64, 64) - shape (64, 64, 1)normed norm(imageimg, maskmask)img, mask [normed[x] for x in [image, mask]]def img_to_batch(x):x np.transpose(x, (2, 0, 1)).astype(float32)return torch.from_numpy(np.expand_dims(x, 0))img, mask map(img_to_batch, (img, mask))criterion F.binary_cross_entropy现在是时候训练一个网络并使其过拟合某一张图像了——正如我所提到的这是一种很好的调试技术model_a UNet(3, 1)optimizer torch.optim.Adam(model_a.parameters(), lr1e-3)losses []for t in tqdm(range(20)):loss criterion(model_a(img), mask)losses.append(loss.item())optimizer.zero_grad()loss.backward()optimizer.step()_ plt.plot(losses)曲率看起来很好但交叉熵的损失值预计不会是 -300。这是怎么了图像的标准化效果很好需要手动将其缩放到 [01]。model_b UNet(3, 1)optimizer torch.optim.Adam(model_b.parameters(), lr1e-3)losses []for t in tqdm(range(20)):loss criterion(model_b(img), mask / 255.)losses.append(loss.item())optimizer.zero_grad()loss.backward()optimizer.step()_ plt.plot(losses)训练循环中一个简单的断言(例如 assert mask.max()1)会很快检测到问题。同样单元测试也可以检测到问题。总而言之测试很重要运行断言可以用于训练管道可视化是一种不错的手段抄袭是一种诅咒没有什么是灵丹妙药机器学习工程师必须时刻小心。雷锋网雷锋网雷锋网
http://www.pierceye.com/news/651806/

相关文章:

  • 织梦手机网站模板删除不了宁波网站建设服务商
  • 深圳网站建设最专业网站seo技术
  • 定制网站开发一般多少钱郑州哪家公司做网站好
  • jsp做的网站效果给你一个网站你怎么做的吗
  • 怎样做网站海报wordpress最近怎么又是5.0更新
  • 淡水网站建设哪家便宜设计网页分析
  • 长沙多迪php网站开发培训学校小说榜单首页百度搜索风云榜
  • 门户网站建设计入什么科目网站备案 时间更新
  • 企业建网站租用服务器好还是买一个好wordpress 预订插件
  • 电气建设网站下载的asp网站怎么打开
  • 南阳网站建设icp备手机应用商店免费下载
  • 网站开发测量像素工具网站模板包含哪些内容
  • 南昌网站排名优化费用湖北公众号定制开发
  • 个人主页自助建站凡科网干嘛的
  • 网站后台上传图片不显示品牌营销咨询公司
  • 卖房网站母亲节做什麽活动从传播的角度
  • 永久免费的cad软件seo咨询
  • 网站邮件功能设计理论网站排名软件包年
  • wordpress语言文件编辑专业的企业网站优化公司
  • 正定网站建设制作公司wordpress去掉模板登录
  • 定制开发一个网站多少钱网站开发项目的心得体会
  • 网站被做跳转怎么办个人网站开发软件
  • 湛江网站制作费用南昌建站系统外包
  • 杭州市住房和城乡建设厅网站网页设计个人网站作业
  • 钦州建站哪家好杭州网站建站平台
  • 程序员做笔记的网站在线简历制作系统
  • 有一个网站自己做链接获取朋友位置wordpress504
  • 设计感 网站wordpress企业内网主题
  • 金塔精神文明建设网站上线了小程序制作平台
  • 东莞阳光网站建设成效网站内容营销