dnn_mod.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. # Copyright (C) 2024 Intel Labs
  2. #
  3. # BSD-3-Clause License
  4. #
  5. # Redistribution and use in source and binary forms, with or without modification,
  6. # are permitted provided that the following conditions are met:
  7. # 1. Redistributions of source code must retain the above copyright notice,
  8. # this list of conditions and the following disclaimer.
  9. # 2. Redistributions in binary form must reproduce the above copyright notice,
  10. # this list of conditions and the following disclaimer in the documentation
  11. # and/or other materials provided with the distribution.
  12. # 3. Neither the name of the copyright holder nor the names of its contributors
  13. # may be used to endorse or promote products derived from this software
  14. # without specific prior written permission.
  15. #
  16. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  18. # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
  20. # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  21. # OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  22. # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  23. # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  24. # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  25. # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  26. # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. #
  28. # Functions related to DNN to BNN model conversion.
  29. #
  30. # @authors: Mahesh Subedar
  31. #
  32. # ===============================================================================================
  33. from __future__ import absolute_import, division, print_function
  34. import bayesian_torch.layers as bayesian_layers
  35. from bayesian_torch.utils.util import get_rho
  36. # --------------------------------------------------------------------------------
  37. # Parameters used to define BNN layyers.
  38. # bnn_prior_parameters = {
  39. # "prior_mu": 0.0,
  40. # "prior_sigma": 1.0,
  41. # "posterior_mu_init": 0.0,
  42. # "posterior_rho_init": -4.0,
  43. # "type": "Reparameterization", # Flipout or Reparameterization
  44. # }
  45. def bnn_linear_layer(params, d):
  46. layer_type = d.__class__.__name__ + params["type"]
  47. layer_fn = getattr(bayesian_layers, layer_type) # Get BNN layer
  48. bnn_layer = layer_fn(
  49. in_features=d.in_features,
  50. out_features=d.out_features,
  51. prior_mean=params["prior_mu"],
  52. prior_variance=params["prior_sigma"],
  53. posterior_mu_init=params["posterior_mu_init"],
  54. posterior_rho_init=params["posterior_rho_init"],
  55. bias=d.bias is not None,
  56. )
  57. # if MOPED is enabled initialize mu and sigma
  58. if params["moped_enable"]:
  59. delta = params["moped_delta"]
  60. bnn_layer.mu_weight.data.copy_(d.weight.data)
  61. bnn_layer.rho_weight.data.copy_(get_rho(d.weight.data, delta))
  62. if bnn_layer.mu_bias is not None:
  63. bnn_layer.mu_bias.data.copy_(d.bias.data)
  64. bnn_layer.rho_bias.data.copy_(get_rho(d.bias.data, delta))
  65. bnn_layer.dnn_to_bnn_flag = True
  66. return bnn_layer
  67. def bnn_conv_layer(params, d):
  68. layer_type = d.__class__.__name__ + params["type"]
  69. layer_fn = getattr(bayesian_layers, layer_type) # Get BNN layer
  70. bnn_layer = layer_fn(
  71. in_channels=d.in_channels,
  72. out_channels=d.out_channels,
  73. kernel_size=d.kernel_size,
  74. stride=d.stride,
  75. padding=d.padding,
  76. dilation=d.dilation,
  77. groups=d.groups,
  78. prior_mean=params["prior_mu"],
  79. prior_variance=params["prior_sigma"],
  80. posterior_mu_init=params["posterior_mu_init"],
  81. posterior_rho_init=params["posterior_rho_init"],
  82. bias=d.bias is not None,
  83. )
  84. # if MOPED is enabled, initialize mu and sigma
  85. if params["moped_enable"]:
  86. delta = params["moped_delta"]
  87. bnn_layer.mu_kernel.data.copy_(d.weight.data)
  88. bnn_layer.rho_kernel.data.copy_(get_rho(d.weight.data, delta))
  89. if bnn_layer.mu_bias is not None:
  90. bnn_layer.mu_bias.data.copy_(d.bias.data)
  91. bnn_layer.rho_bias.data.copy_(get_rho(d.bias.data, delta))
  92. bnn_layer.dnn_to_bnn_flag = True
  93. return bnn_layer
  94. def bnn_lstm_layer(params, d):
  95. layer_type = d.__class__.__name__ + params["type"]
  96. layer_fn = getattr(bayesian_layers, layer_type) # Get BNN layer
  97. bnn_layer = layer_fn(
  98. in_features=d.input_size,
  99. out_features=d.hidden_size,
  100. prior_mean=params["prior_mu"],
  101. prior_variance=params["prior_sigma"],
  102. posterior_mu_init=params["posterior_mu_init"],
  103. posterior_rho_init=params["posterior_rho_init"],
  104. bias=d.bias is not None,
  105. )
  106. # if MOPED is enabled initialize mu and sigma
  107. if params["moped_enable"]:
  108. print("WARNING: MOPED method is not supported for LSTM layers!!!")
  109. bnn_layer.dnn_to_bnn_flag = True
  110. return bnn_layer
  111. # replaces linear and conv layers
  112. # bnn_prior_parameters - check the template at the top.
  113. # MODIFICATION - PREVENT DOUBLE CONVERSION OF DNN TO BNN LAYERS. IF THE LAYER IS ALREADY CONVERTED, SKIP IT.
  114. def dnn_to_bnn_mod(m, bnn_prior_parameters):
  115. for name, value in list(m._modules.items()):
  116. # SKIP LAYERS THAT ARE ALREADY CONVERTED TO BNN LAYERS - ENDS IN "Reparameterization" OR "Flipout"
  117. if m._modules[name].__class__.__name__.endswith(
  118. "Reparameterization"
  119. ) or m._modules[name].__class__.__name__.endswith("Flipout"):
  120. continue
  121. if m._modules[name]._modules:
  122. dnn_to_bnn_mod(m._modules[name], bnn_prior_parameters)
  123. elif "Conv" in m._modules[name].__class__.__name__:
  124. setattr(m, name, bnn_conv_layer(bnn_prior_parameters, m._modules[name]))
  125. elif "Linear" in m._modules[name].__class__.__name__:
  126. setattr(m, name, bnn_linear_layer(bnn_prior_parameters, m._modules[name]))
  127. elif "LSTM" in m._modules[name].__class__.__name__:
  128. setattr(m, name, bnn_lstm_layer(bnn_prior_parameters, m._modules[name]))
  129. else:
  130. pass
  131. return
  132. def get_kl_loss(m):
  133. kl_loss = None
  134. for layer in m.modules():
  135. if hasattr(layer, "kl_loss"):
  136. if kl_loss is None:
  137. kl_loss = layer.kl_loss()
  138. else:
  139. kl_loss += layer.kl_loss()
  140. return kl_loss