- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
请参阅下面的 EDIT ,最初的帖子现在几乎没有任何意义,但问题仍然存在。
我开发了一个神经网络来语义分割图像。我研究了各种损失函数(分类交叉熵 (CCE)、权重 CCE、焦点损失、tversky 损失、jaccard 损失、焦点 tversky 损失等),这些函数试图处理高度偏斜的类表示,但都没有产生预期的效果。我的顾问提到尝试创建一个自定义损失函数,该函数忽略特定类别的误报(但仍会惩罚误报)。
我有一个 6 类问题,我的网络设置为在单热编码的真实数据中工作/使用。因此,我的损失函数将接受两个张量 y_true, y_pred
,形状为 (batch, row, col, class)
(当前为 (8, 128, 128, 6)
)。为了能够利用我已经探索过的损失,我想更改 y_pred
以将特定类别(第 0 个类别)的预测值设置为始终正确。这就是 y_true == class 0
设置 y_pred == class 0
的地方,否则什么都不做。
由于 tensorflow 张量是不可变的,我花了太多时间试图创建这个损失函数。我的第一次尝试(我是通过我对 numpy
的经验而获得的)
def weighted_categorical_crossentropy_ignore(weights):
weights = K.variable(weights)
def loss(y_true, y_pred):
y_pred[tf.where(y_true == [1, 0, 0, 0, 0, 0])] = [1, 0, 0, 0, 0, 0]
# Scale predictions so that the class probs of each sample sum to 1
y_pred /= K.sum(y_pred, axis=-1, keepdims=True)
# Clip to prevent NaN's and Inf's
y_pred = K.clip(y_pred, K.epsilon(), 1 - K.epsilon())
loss = y_true * K.log(y_pred) * weights
loss = -K.sum(loss, -1)
return loss
return loss
虽然显然我不能改变
y_pred
所以这次尝试失败了。我最终创建了一些怪物,试图通过迭代
[batch, row, col]
并进行比较来“构建”张量。虽然这种(ese)尝试在技术上没有失败,但他们从未真正开始训练。我认为计算损失需要几分钟的时间。
numpy
执行必要的计算。但是保持认知我基本上仅限于实例化“简单”张量(即
ones
、
zeros
)并且只执行“简单”操作,如逐元素乘法、加法和整形。于是我来到了这个 SSCCE
import numpy as np
from tensorflow.keras.utils import to_categorical
# Generate the "images" at random
true_flat = np.argmax(np.random.rand(1, 2, 2, 4), axis=3).astype('int')
true = to_categorical(true_flat, num_classes=4).astype('int')
pred_flat = np.argmax(np.random.rand(1, 2, 2, 4), axis=3).astype('int')
pred = to_categorical(pred_flat, num_classes=4).astype('int')
print('True:\n', true_flat)
print('Pred:\n', pred_flat)
# Create a mask representing an all "class 0" image
class_zero_label = np.array([1, 0, 0, 0])
czl_all = class_zero_label * np.ones(true.shape).astype('int')
# Mask both the truth and pred to locate class 0 pixels
czl_true_locs = czl_all * true
czl_pred_locs = czl_all * pred
# Subtract to create "addition" matrix
a = (czl_true_locs - czl_pred_locs) * czl_true_locs
print('a:\n', a)
# Do this
m = ((a + 1) - (a * 2))
print('m - ', m.shape, ':\n', m)
# Pull the front entry from 'm' and "expand" its value
#x = (m[:, :, :, 0].flatten() * np.ones(pred.shape).astype('int')).T.reshape(pred.shape)
m_front = m[:, :, :, 0]
print('m_front - ', m_front.shape, ':\n', m_front)
#m_flat = m_front.flatten()
m_flat = m_front.reshape(m_front.shape[0], m_front.shape[1]*m_front.shape[2])
print('m_flat - ', m_flat.shape, ':\n', m_flat)
m_expand = m_flat * np.ones(pred.shape).astype('int')
print('m_expand - ', m_expand.shape, ':\n', m_expand)
m_trans = m_expand.T
m_fixT = m_trans.reshape(pred.shape)
print('m_fixT - ', m_fixT.shape, ':\n', m_fixT)
m = m_fixT
print('m:\n', m.shape)
# Perform the math as described
pred = (pred * m) + a
print('Pred:\n', np.argmax(pred, axis=3))
这个 SSCCE,很好,很糟糕,很复杂。基本上我的目标是创建两个矩阵,“加法”和“乘法”矩阵。乘法矩阵旨在将预测值中的每个像素“归零”,其中真值等于 0 类。这与像素值(即单热编码向量)将其归零以等于
[0, 0, 0, 0, 0, 0]
无关.然后,加法矩阵将向量
[1, 0, 0, 0, 0, 0]
添加到每个归零的位置。最终,这将实现将每个真正的 0 类像素的预测值设置为正确的目标。
batch_size > 1
时没有正确定义。我想没关系,只是为了看看它是否有效,我会分解
tf.unstack
y_true
和
y_pred
张量并对其进行迭代。这导致我对我的损失函数进行了当前的实例化
def weighted_categorical_crossentropy_ignore(weights):
weights = K.variable(weights)
def loss(y_true, y_pred):
y_true_un = tf.unstack(y_true)
y_pred_un = tf.unstack(y_pred)
y_pred_new = []
for i in range(0, y_true.shape[0]):
yt = y_true_un[i]
yp = y_pred_un[i]
# Pred:
# [[[0 3] * [[[1 0] + [[[0 1] = [[[0 0]
# [3 1]]] [[1 1]]] [[0 0]]] [[3 1]]]
# If we multiple pred by a tensor which zeros out only incorrect class 0 labelleling
# Then add class zero to those zero'd out locations
# We can negate the effect of mis-classified class 0 pixels but still punish for
# incorrectly predicted class 0 labels for other classes.
# Create a mask respresenting an all "class 0" image
class_zero_label = K.variable([1.0, 0.0, 0.0, 0.0, 0.0, 0.0])
czl_all = class_zero_label * K.ones(yt.shape)
# Mask both true and pred to locate class 0 pixels
czl_true = czl_all * yt
czl_pred = czl_all * yp
# Subtract to create "addition matrix"
a = czl_true - czl_pred
# Do this.
m = ((a + 1) - (a * 2.))
# And this.
x = K.flatten(m[:, :, 0])
x = x * K.ones(yp.shape)
x = K.transpose(x)
x = K.reshape(x, yp.shape)
# Voila.
ypnew = (yp * x) + a
y_pred_new.append(ypnew)
y_pred_new = tf.concat(y_pred_new, 0)
# Continue calculating weighted categorical crossentropy
# -------------------------------------------------------
# Scale predictions so that the class probs of each sample sum to 1
y_pred_new /= K.sum(y_pred_new, axis=-1, keepdims=True)
# Clip to prevent NaN's and Inf's
y_pred_new = K.clip(y_pred_new, K.epsilon(), 1 - K.epsilon())
loss = y_true * K.log(y_pred_new) * weights
loss = -K.sum(loss, -1)
return loss
return loss
此损失函数的当前问题在于执行操作时
numpy
和
tensorflow
之间的行为存在明显差异
x = K.flatten(m[:, :, 0])
x = x * K.ones(yp.shape)
这意味着代表行为
m_flat = m_front.flatten()
m_expand = m_flat * np.ones(pred.shape).astype('int')
来自 SSCCE。
y_pred[tf.where(y_true == [1, 0, 0, 0, 0, 0])] = [1, 0, 0, 0, 0, 0]
在自定义 tensorflow 损失函数中?
.numpy()
、
y_true
张量上调用
y_pred
以使用
numpy
的 0x1045 设置操作 0x1046t 的 791045 次“7”
tf.compat.v1.enable_eager_execution
到
run_eagerly=True
)。
def weighted_categorical_crossentropy_ignore(weights):
weights = K.variable(weights)
def loss(y_true, y_pred):
yp = y_pred.numpy()
yt = y_true.numpy()
yp[np.nonzero(np.all(yt == [1, 0, 0, 0, 0, 0], axis=3))] = [1, 0, 0, 0, 0, 0]
# Continue calculating weighted categorical crossentropy
# -------------------------------------------------------
# Scale predictions so that the class probs of each sample sum to 1
yp /= K.sum(yp, axis=-1, keepdims=True)
# Clip to prevent NaN's and Inf's
yp = K.clip(yp, K.epsilon(), 1 - K.epsilon())
loss = y_true * K.log(yp) * weights
loss = -K.sum(loss, -1)
return loss
return loss
尽管似乎通过调用
Model().compile(...)
(或此后使用它),我显然已经“破坏”了通过网络的路径/流。基于尝试
y_pred.numpy()
时的错误
ValueError: No gradients provided for any variable: ['conv3d/kernel:0', <....>
我想我不知何故需要将张量“重新编码”回 GPU 内存?我试过了
yp = tf.convert_to_tensor(yp)
无济于事;同样的错误。所以我想同样的问题仍然存在,但出于不同的动机..
.fit
来编码
numpy()
,
y_true
到 1
y_pred
到 9这必然会“破坏”网络路径,因此无法计算梯度。
numpy
我可以
run_eagerly=True
我的
tf.Variable
/
y_true
并执行分配。所以在纯 tensorflow 中我试图再次重新创建相同的代码
def weighted_categorical_crossentropy_ignore(weights):
weights = K.variable(weights)
def loss(y_true, y_pred):
# yp = y_pred.numpy().copy()
# yt = y_true.numpy().copy()
# yp[np.nonzero(np.all(yt == [1, 0, 0, 0, 0, 0], axis=3))] = [1, 0, 0, 0, 0, 0]
yp = K.variable(y_pred)
yt = K.variable(y_true)
#np.all
x = K.all(yt == [1, 0, 0, 0, 0, 0], axis=3)
#np.nonzero
ne = tf.not_equal(x, tf.constant(False))
y = tf.where(ne)
# Perform the desired operation
yp[y] = [1, 0, 0, 0, 0, 0]
# Continue calculating weighted categorical crossentropy
# -------------------------------------------------------
# Scale predictions so that the class probs of each sample sum to 1
#yp /= K.sum(yp, axis=-1, keepdims=True) # Cannot use \= on tf.var, must use var = var /
yp = yp / K.sum(yp, axis=-1, keepdims=True)
# Clip to prevent NaN's and Inf's
yp = K.clip(yp, K.epsilon(), 1 - K.epsilon())
loss = y_true * K.log(yp) * weights
loss = -K.sum(loss, -1)
return loss
return loss
但唉,这显然会产生与调用
y_pred
时相同的问题;无法计算梯度。所以我似乎又回到了广场 1。
def weighted_categorical_crossentropy_ignore(weights):
weights = K.variable(weights)
def loss(y_true, y_pred):
print('y_true.shape: ', y_true.shape)
print('y_pred.shape: ', y_pred.shape)
# Generate modified y_pred where all truly class0 pixels are correct
y_true_class0_indicies = tf.where(tf.math.equal(y_true, [1., 0., 0., 0., 0., 0.]))
y_pred_updates = tf.repeat([
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0]],
repeats=y_true_class0_indicies.shape[0],
axis=0)
yp = tf.tensor_scatter_nd_update(y_pred, y_true_class0_indicies, y_pred_updates)
# Continue calculating weighted categorical crossentropy
# -------------------------------------------------------
# Scale predictions so that the class probs of each sample sum to 1
yp /= K.sum(yp, axis=-1, keepdims=True)
# Clip to prevent NaN's and Inf's
yp = K.clip(yp, K.epsilon(), 1 - K.epsilon())
loss = y_true * K.log(yp) * weights
loss = -K.sum(loss, -1)
return loss
return loss
如果原始答案假定
.numpy()
的形状为
y_true
(即“平面”类表示,而不是单热编码表示
[8, 128, 128]
),我首先打印
[8, 128, 128, 6]
和
y_true
输入的形状
y_true.shape: (8, 128, 128, 6)
y_pred.shape: (8, 128, 128, 6)
为了进一步的理智,由
y_pred
的尾部提供的网络输出形状是
conv2d_18 (Conv2D) (None, 128, 128, 6) 1542 dropout_5[0][0]
__________________________________________________________________________________________________
activation_9 (Activation) (None, 128, 128, 6) 0 conv2d_18[0][0]
==================================================================================================
Total params: 535,551,494
Trainable params: 535,529,478
Non-trainable params: 22,016
__________________________________________________________________________________________________
然后我按照建议的解决方案中的“模式”,用
model.summary
替换原来的
tf.math.equal(y_true, 0)
来处理单热编码的情况。根据我目前对提议的解决方案的理解(经过约 10 分钟的检查),我认为这应该可行。尽管在尝试训练模型时会引发以下异常
InvalidArgumentError: Inner dimensions of output shape must match inner dimensions of updates shape. Output: [8,128,128,6] updates: [684584,6] [Op:TensorScatterUpdate]
因此,似乎(正如我给它们命名的那样)
tf.math.equal(y_true, [1., 0., 0., 0., 0., 0.])
的产生产生了一个具有“太多”元素的“折叠”张量。我理解使用
y_pred_updates
的动机,但它的具体用途似乎不正确。我认为它应该根据我对
tf.repeat
的理解产生形状为
(8, 128, 128, 6)
的张量。我认为这很可能只是基于在调用
tf.tensor_scatter_nd_update
期间对
repeats
和
axis
的选择。
最佳答案
如果我正确理解你的问题,你正在寻找这样的东西:
import tensorflow as tf
# batch of true labels
y_true = tf.constant([5, 0, 1, 3, 4, 0, 2, 0], dtype=tf.int64)
# batch of class probabilities
y_pred = tf.constant(
[
[0.34670502, 0.04551039, 0.14020428, 0.14341979, 0.21430719, 0.10985339],
[0.25681055, 0.14013883, 0.19890164, 0.11124421, 0.14526634, 0.14763844],
[0.09199252, 0.21889475, 0.1170236 , 0.1929019 , 0.20311192, 0.17607528],
[0.3246354 , 0.23257554, 0.15549366, 0.17282239, 0.00000001, 0.11447308],
[0.16502093, 0.13163856, 0.14371352, 0.19880624, 0.23360236, 0.12721846],
[0.27362782, 0.21408406, 0.10917682, 0.13135742, 0.10814326, 0.16361059],
[0.20697299, 0.23721898, 0.06455399, 0.11071447, 0.18990229, 0.19063729],
[0.10320242, 0.22173141, 0.2547973 , 0.2314068 , 0.07063974, 0.11822232]
], dtype=tf.float32)
# find the indices in the batch where the true label is the class 0
indices = tf.where(tf.math.equal(y_true, 0))
# create a tensor with the number of updates you want to replace in `y_pred`
updates = tf.repeat(
[[1.0, 0.0, 0.0, 0.0, 0.0, 0.0]],
repeats=indices.shape[0],
axis=0)
# insert the updates into `y_pred` at the specified indices
modified_y_pred = tf.tensor_scatter_nd_update(y_pred, indices, updates)
print(modified_y_pred)
# tf.Tensor(
# [[0.34670502, 0.04551039, 0.14020428, 0.14341979, 0.21430719, 0.10985339],
# [1.00000000, 0.00000000, 0.00000000, 0.00000000, 0.00000000, 0.00000000],
# [0.09199252, 0.21889475, 0.1170236 , 0.1929019 , 0.20311192, 0.17607528],
# [0.3246354 , 0.23257554, 0.15549366, 0.17282239, 0.00000001, 0.11447308],
# [0.16502093, 0.13163856, 0.14371352, 0.19880624, 0.23360236, 0.12721846],
# [1.00000000, 0.00000000, 0.00000000, 0.00000000, 0.00000000, 0.00000000],
# [0.20697299, 0.23721898, 0.06455399, 0.11071447, 0.18990229, 0.19063729],
# [1.00000000, 0.00000000, 0.00000000, 0.00000000, 0.00000000, 0.00000000]],
# shape=(8, 6), dtype=tf.float32)
这个最终的张量,
modified_y_pred
,可用于微分。
# these arent normalized to 1 but you get the point
probs = tf.random.normal([2, 4, 4, 6])
# raw labels per pixel
labels = tf.random.uniform(
shape=[2, 4, 4],
minval=0,
maxval=6,
dtype=tf.int64)
# your labels are already one-hot encoded
labels = tf.one_hot(labels, 6)
# boolean mask where classes are `0`
# converting back to int labels with argmax for purposes of
# using `tf.math.equal`. Matching on `[1, 0, 0, 0, 0, 0]` is
# potentially buggy; matching on an integer is a lot more
# explicit.
mask = tf.math.equal(tf.math.argmax(labels, -1), 0)[..., None]
# flip the mask to zero out the pixels across channels where
# labels are zero
probs *= tf.cast(tf.math.logical_not(mask), tf.float32)
# multiply the mask by the one-hot labels, and add back
# to the already masked probabilities.
probs += labels * tf.cast(mask, tf.float32)
关于python - Keras 自定义损失函数在语义分割期间忽略特定类的漏报?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66084314/
好的,所以我编辑了以下... 只需将以下内容放入我的 custom.css #rt-utility .rt-block {CODE HERE} 但是当我尝试改变... 与 #rt-sideslid
在表格 View 中,我有一个自定义单元格(在界面生成器中高度为 500)。在该单元格中,我有一个 Collection View ,我按 (10,10,10,10) 固定到边缘。但是在 tablev
对于我的无能,我很抱歉,但总的来说,我对 Cocoa、Swift 和面向对象编程还很陌生。我的主要来源是《Cocoa Programming for OS X》(第 5 版),以及 Apple 的充满
我正在使用 meta-tegra 为我的 NVIDIA Jetson Nano 构建自定义图像。我需要 PyTorch,但没有它的配方。我在设备上构建了 PyTorch,并将其打包到设备上的轮子中。现
在 jquery 中使用 $.POST 和 $.GET 时,有没有办法将自定义变量添加到 URL 并发送它们?我尝试了以下方法: $.ajax({type:"POST", url:"file.php?
Traefik 已经默认实现了很多中间件,可以满足大部分我们日常的需求,但是在实际工作中,用户仍然还是有自定义中间件的需求,为解决这个问题,官方推出了一个 Traefik Pilot[1] 的功
我想让我的 CustomTextInputLayout 将 Widget.MaterialComponents.TextInputLayout.OutlinedBox 作为默认样式,无需在 XML 中
我在 ~/.emacs 中有以下自定义函数: (defun xi-rgrep (term) (grep-compute-defaults) (interactive "sSearch Te
我有下表: 考虑到每个月的权重,我的目标是在 5 个月内分散 10,000 个单位。与 10,000 相邻的行是我最好的尝试(我在这上面花了几个小时)。黄色是我所追求的。 我试图用来计算的逻辑如下:计
我的表单中有一个字段,它是文件类型。当用户点击保存图标时,我想自然地将文件上传到服务器并将文件名保存在数据库中。我尝试通过回显文件名来测试它,但它似乎不起作用。另外,如何将文件名添加到数据库中?是在模
我有一个 python 脚本来发送电子邮件,它工作得很好,但问题是当我检查我的电子邮件收件箱时。 我希望该用户名是自定义用户名,而不是整个电子邮件地址。 最佳答案 发件人地址应该使用的格式是: You
我想减小 ggcorrplot 中标记的大小,并减少文本和绘图之间的空间。 library(ggcorrplot) data(mtcars) corr <- round(cor(mtcars), 1)
GTK+ noob 问题在这里: 是否可以自定义 GtkFileChooserButton 或 GtkFileChooserDialog 以删除“位置”部分(左侧)和顶部的“位置”输入框? 我实际上要
我正在尝试在主页上使用 ajax 在 magento 中使用 ajax 显示流行的产品列表,我可以为 5 或“N”个产品执行此操作,但我想要的是将分页工具栏与结果集一起添加. 这是我添加的以显示流行产
我正在尝试使用 PasswordResetForm 内置函数。 由于我想要自定义表单字段,因此我编写了自己的表单: class FpasswordForm(PasswordResetForm):
据我了解,新的 Angular 7 提供了拖放功能。我搜索了有关 DnD 的 Tree 组件,但没有找到与树相关的内容。 我在 Stackblitz 上找到的一个工作示例.对比drag'ndrop功能
我必须开发一个自定义选项卡控件并决定使用 WPF/XAML 创建它,因为我无论如何都打算学习它。完成后应该是这样的: 到目前为止,我取得了很好的进展,但还有两个问题: 只有第一个/最后一个标签项应该有
我要定制xtable用于导出到 LaTeX。我知道有些问题是关于 xtable在这里,但我找不到我要找的具体东西。 以下是我的表的外观示例: my.table <- data.frame(Specif
用ejs在这里显示日期 它给我结果 Tue Feb 02 2016 16:02:24 GMT+0530 (IST) 但是我需要表现为 19th January, 2016 如何在ejs中执行此操作?
我想问在 JavaFX 中使用自定义对象制作 ListView 的最佳方法,我想要一个每个项目如下所示的列表: 我搜了一下,发现大部分人都是用细胞工厂的方法来做的。有没有其他办法?例如使用客户 fxm
我是一名优秀的程序员,十分优秀!