Belle II Software  light-2212-foldex
tensorflow.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 
11 
12 import numpy as np
13 import sys
14 import os
15 import tempfile
16 
17 
18 class State(object):
19  """
20  Tensorflow state
21  """
22 
23  def __init__(self, model=None, **kwargs):
24  """ Constructor of the state object """
25 
26 
27  self.modelmodel = model
28 
29 
30 def feature_importance(state):
31  """
32  Return a list containing the feature importances
33  """
34  return []
35 
36 
37 def get_model(number_of_features, number_of_spectators, number_of_events, training_fraction, parameters):
38  """
39  Return default tensorflow model
40  """
41  try:
42  import tensorflow as tf
43  except ImportError:
44  print("Please install tensorflow: pip3 install tensorflow")
45  sys.exit(1)
46 
47  gpus = tf.config.list_physical_devices('GPU')
48  if gpus:
49  for gpu in gpus:
50  tf.config.experimental.set_memory_growth(gpu, True)
51 
52  class my_model(tf.Module):
53 
54  def __init__(self, **kwargs):
55 
56  super().__init__(**kwargs)
57 
58  self.W = tf.Variable(tf.ones(shape=(number_of_features, 1)), name="W")
59  self.b = tf.Variable(tf.ones(shape=(1, 1)), name="b")
60 
61  self.optimizer = tf.optimizers.SGD(0.01)
62 
63  @tf.function(input_signature=[tf.TensorSpec(shape=[None, number_of_features], dtype=tf.float32)])
64  def __call__(self, x):
65  return tf.nn.sigmoid(tf.matmul(self.clean_nans(x), self.W) + self.b)
66 
67  def clean_nans(self, x):
68  return tf.where(tf.math.is_nan(x), tf.zeros_like(x), x)
69 
70  def loss(self, predicted_y, target_y, w):
71  # cross entropy
72  epsilon = 1e-5
73  diff_from_truth = tf.where(target_y == 1., predicted_y, 1. - predicted_y)
74  return - tf.reduce_sum(w * tf.math.log(diff_from_truth + epsilon)) / tf.reduce_sum(w)
75 
76  state = State(model=my_model())
77  return state
78 
79 
80 def load(obj):
81  """
82  Load Tensorflow estimator into state
83  """
84  try:
85  import tensorflow as tf
86  except ImportError:
87  print("Please install tensorflow: pip3 install tensorflow")
88  sys.exit(1)
89 
90  gpus = tf.config.list_physical_devices('GPU')
91  if gpus:
92  for gpu in gpus:
93  tf.config.experimental.set_memory_growth(gpu, True)
94 
95  with tempfile.TemporaryDirectory() as path:
96 
97  # recreate the expected folder structure
98  for subfolder in ['variables', 'assets']:
99  os.makedirs(os.path.join(path, subfolder))
100 
101  file_names = obj[0]
102  for file_index, file_name in enumerate(file_names):
103  with open(f'{path}/{file_name}', 'w+b') as file:
104  file.write(bytes(obj[1][file_index]))
105 
106  model = tf.saved_model.load(path)
107 
108  state = State(model=model)
109  return state
110 
111 
112 def apply(state, X):
113  """
114  Apply estimator to passed data.
115  """
116  try:
117  import tensorflow as tf
118  except ImportError:
119  print("Please install tensorflow: pip3 install tensorflow")
120  sys.exit(1)
121 
122  r = state.model(tf.convert_to_tensor(np.atleast_2d(X), dtype=tf.float32)).numpy()
123  if r.shape[1] == 1:
124  r = r[:, 0] # cannot use squeeze because we might have output of shape [1,X classes]
125  return np.require(r, dtype=np.float32, requirements=['A', 'W', 'C', 'O'])
126 
127 
128 def begin_fit(state, Xtest, Stest, ytest, wtest, nBatches):
129  """
130  Returns just the state object
131  """
132  state.nBatches = nBatches
133  return state
134 
135 
136 def partial_fit(state, X, S, y, w, epoch, batch):
137  """
138  Pass batches of received data to tensorflow
139  """
140  try:
141  import tensorflow as tf
142  except ImportError:
143  print("Please install tensorflow: pip3 install tensorflow")
144  sys.exit(1)
145 
146  with tf.GradientTape() as tape:
147  avg_cost = state.model.loss(state.model(X), y, w)
148  grads = tape.gradient(avg_cost, state.model.trainable_variables)
149 
150  state.model.optimizer.apply_gradients(zip(grads, state.model.trainable_variables))
151 
152  if batch == 0 and epoch == 0:
153  state.avg_costs = [avg_cost]
154  elif batch != state.nBatches-1:
155  state.avg_costs.append(avg_cost)
156  else:
157  # end of the epoch, print summary results, reset the avg_costs and update the counter
158  print(f"Epoch: {epoch:04d} cost= {np.mean(state.avg_costs):.9f}")
159  state.avg_costs = [avg_cost]
160 
161  if epoch == 100000:
162  return False
163  return True
164 
165 
166 def end_fit(state):
167  """
168  Store tensorflow model in a graph
169  """
170  try:
171  import tensorflow as tf
172  except ImportError:
173  print("Please install tensorflow: pip3 install tensorflow")
174  sys.exit(1)
175  with tempfile.TemporaryDirectory() as path:
176 
177  tf.saved_model.save(state.model, path)
178  # tf.saved_model.save creates:
179  # path/saved_model.pb
180  # path/variables/variables.index
181  # path/variables/variables.data-00000-of-00001
182  # path/assets/* - This contains additional assets stored in the model.
183 
184  file_names = ['saved_model.pb',
185  'variables/variables.index',
186  'variables/variables.data-00000-of-00001']
187 
188  # we dont know what, if anything, is saved in assets/
189  assets_path = os.path.join(path, 'assets/')
190  file_names.extend([f'assets/{f.name}' for f in os.scandir(assets_path) if os.path.isfile(os.path.join(assets_path, f))])
191 
192  files = []
193  for file_name in file_names:
194  with open(os.path.join(path, file_name), 'rb') as file:
195  files.append(file.read())
196  del state
197  return [file_names, files]
model
tensorflow model inheriting from tf.Module
Definition: tensorflow.py:27
def __init__(self, model=None, **kwargs)
Definition: tensorflow.py:23