Unexpected Error when Optimizing over Directional Light #668
-
Hi @njroussel, I am trying to use mitsuba to optimize the intensity of two light sources, with one being constant enviroment light and the other being directional light. The code snippet is as below and can run sucessfully for both keys either import drjit as dr
import mitsuba as mi
mi.set_variant('cuda_ad_rgb')
import torch
import torch.nn as nn
import torch.nn.functional as F
from matplotlib import pyplot as plt
from mitsuba.scalar_rgb import Transform4f as T
filenames = [
'mitsuba/scenes/textures/flower_photo_downscale.jpeg',
]
textures = [
mi.TensorXf(mi.Bitmap(f).convert(mi.Bitmap.PixelFormat.RGB, mi.Struct.Type.Float32))
for f in filenames
]
res = dr.shape(textures[0])[0]
scene = mi.load_dict({
'type': 'scene',
'integrator': {
'type': 'direct_reparam',
},
'sensor': {
'type': 'perspective',
'to_world': T.look_at(
origin=(0, 0, -2),
target=(0, 0, 0),
up=(0, -1, 0)
),
'fov': 60,
'film': {
'type': 'hdrfilm',
'width': res,
'height': res,
'sample_border': True,
},
},
'textured_plane': {
'type': 'rectangle',
'to_world': T.scale(1.2),
'bsdf': {
'type': 'twosided',
'nested': {
'type': 'diffuse',
'reflectance': {
'type': 'bitmap',
'filename': filenames[0]
},
}
}
},
'const_env_light': {
'type': 'constant',
'radiance': {
'type': 'rgb',
'value': 0.5,
}
},
'directional_light': {
'type': 'directional',
'direction': [0, 0, 1],
'irradiance': {
'type': 'rgb',
'value': 5,
}
},
})
params = mi.traverse(scene)
print(params)
optim_params = {
'const_env_light.radiance.value': torch.full((1, 3), 0.5, device='cuda', requires_grad=True),
'directional_light.irradiance.value': torch.full((1, 3), 5.0, device='cuda', requires_grad=True),
}
# key = 'const_env_light.radiance.value'
key = 'directional_light.irradiance.value'
dr.enable_grad(params[key])
@dr.wrap_ad(source='torch', target='drjit')
def render(value, spp=256):
params[key] = dr.unravel(mi.Color3f, value)
params.update()
return mi.render(scene, params, spp=spp)
optimizer = torch.optim.Adam(optim_params.values(), lr=0.0002)
loss_fn = nn.L1Loss()
# Optimization hyper-parameters
iteration_count = 100
spp = 4
train_losses = []
for i in range(iteration_count):
loss_accum = 0
optimizer.zero_grad()
rendered_img = render(optim_params[key], spp=spp)
loss = loss_fn(rendered_img, textures[0].torch())
loss.backward()
loss_accum += loss.item()
optimizer.step()
train_losses.append(loss_accum)
print(f'Training iteration {i+1}/{iteration_count}, loss: {train_losses[-1]}', end='\r') However, when I change the integrator from
and accordingly change the predication from TypeError: backward_from(): the argument does not depend on the input variable(s) being differentiated. Raising an exception since this is usually indicative of a bug (for example, you may have forgotten to call dr.enable_grad(..)). If this is expected behavior, skip the call to backward_from(..) if dr.grad_enabled(..) returns False. Strangely, everything is ok for optimization over I've also experimented with 'integrator': {
'type': 'aov',
'aovs': 'shape_idx:shape_index',
'image': {
'type': 'direct',
}
}, The optimization is fine for both Since in my case I need |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 6 replies
-
Hi @shallowtoil Could you send the snippet that fails without PyTorch? |
Beta Was this translation helpful? Give feedback.
-
Hi @njroussel, import drjit as dr
import mitsuba as mi
mi.set_variant('cuda_ad_rgb')
from mitsuba.scalar_rgb import Transform4f as T
filenames = [
'mitsuba/scenes/textures/flower_photo_downscale.jpeg',
]
textures = [
mi.TensorXf(mi.Bitmap(f).convert(mi.Bitmap.PixelFormat.RGB, mi.Struct.Type.Float32))
for f in filenames
]
res = dr.shape(textures[0])[0]
scene = mi.load_dict({
'type': 'scene',
'integrator': {
'type': 'aov',
'aovs': 'shape_idx:shape_index',
'image': {
'type': 'direct_reparam',
}
},
'sensor': {
'type': 'perspective',
'to_world': T.look_at(
origin=(0, 0, -2),
target=(0, 0, 0),
up=(0, -1, 0)
),
'fov': 60,
'film': {
'type': 'hdrfilm',
'width': res,
'height': res,
'sample_border': True,
},
},
'textured_plane': {
'type': 'rectangle',
'to_world': T.scale(1.2),
'bsdf': {
'type': 'twosided',
'nested': {
'type': 'diffuse',
'reflectance': {
'type': 'bitmap',
'filename': filenames[0]
},
}
}
},
'const_env_light': {
'type': 'constant',
'radiance': {
'type': 'rgb',
'value': 0.5,
}
},
'directional_light': {
'type': 'directional',
'direction': [0, 0, 1],
'irradiance': {
'type': 'rgb',
'value': 5,
}
},
})
params = mi.traverse(scene)
print(params)
# key = 'const_env_light.radiance.value'
key = 'directional_light.irradiance.value'
dr.enable_grad(params[key])
optimizer = mi.ad.Adam(lr=0.025)
optimizer[key] = params[key]
params.update(optimizer)
loss_fn = lambda x, y: dr.mean(dr.sqr(x - y))
# Optimization hyper-parameters
iteration_count = 100
spp = 4
train_losses = []
for i in range(iteration_count):
loss_accum = 0
rendered_img = mi.render(scene, params, spp=spp)
loss = loss_fn(rendered_img[..., :3], textures[0])
dr.backward(loss)
loss_accum += loss
optimizer.step()
train_losses.append(loss_accum)
params.update(optimizer)
print(f'Training iteration {i+1}/{iteration_count}, loss: {train_losses[-1]}', end='\r') |
Beta Was this translation helpful? Give feedback.
-
Hi @njroussel, Will you consider fixing this bug? I can use the workaround temporarily. Since rendering twice will double the cost, it would be great if the bug can be fixed anytime soon. |
Beta Was this translation helpful? Give feedback.
There's no plan to work on this anytime soon. It would either require a lot of refactoring of the exisiting AOV integrator, or rewriting it entirely in Python.
The cost for the extra rendering shouldn't be that large. Basically the one that uses the
AOV
integrator doesn't need to do a full-depth rendering. All you want is theshape_index
so this should be enoughThis is basically
width x height
more ray intersections which should be marginal.