1
+ import numpy as np
2
+ import tensorflow as tf
3
+ from tensorflow .keras .layers import Dense , Input , Add , Activation
4
+ from tensorflow .keras .models import Model
5
+ from tensorflow .keras .optimizers import Adam
6
+ from tensorflow .keras .losses import MeanSquaredError
7
+ import matplotlib .pyplot as plt
8
+
9
+ # Generate training data
10
+ def generate_data (num_samples = 10000 ):
11
+ x = np .random .uniform (- 3 , 3 , (num_samples ))
12
+ y = 2 ** (- x )
13
+ return x , y
14
+
15
+ # Generate training and validation data
16
+ x_train , y_train = generate_data (2000 )
17
+ x_val , y_val = generate_data (300 )
18
+
19
+ # Define the model with skip connections
20
+ input_layer = Input (shape = (1 ,), name = 'INPUT' )
21
+
22
+ # First hidden layer with skip connection
23
+ hidden1 = Dense (2 , activation = 'relu' , name = 'FC1' )(input_layer )
24
+
25
+ # Output layer with skip connection
26
+ output_layer = Dense (1 , name = 'FC2' )(hidden1 )
27
+ skip_output = Dense (1 , use_bias = False , name = 'SKIP2' )(input_layer )
28
+ output_layer = Add (name = 'Z1' )([output_layer , skip_output ])
29
+
30
+ model = Model (inputs = input_layer , outputs = output_layer )
31
+
32
+ # Initialize the optimizer
33
+ optimizer = Adam (learning_rate = 0.01 )
34
+
35
+ # Training parameters
36
+ epochs = 100
37
+ batch_size = 32
38
+ steps_per_epoch = x_train .shape [0 ] // batch_size
39
+
40
+ # Instantiate the loss function
41
+ mse_loss = MeanSquaredError ()
42
+
43
+ # Training loop
44
+ for epoch in range (epochs ):
45
+ for step in range (steps_per_epoch ):
46
+ # Get a batch of training data
47
+ x_batch = x_train [step * batch_size :(step + 1 )* batch_size ]
48
+ y_batch = y_train [step * batch_size :(step + 1 )* batch_size ]
49
+
50
+ with tf .GradientTape () as tape :
51
+ # Forward pass
52
+ y_pred = model (x_batch , training = True )
53
+ # Compute the loss
54
+ loss = mse_loss (y_batch , y_pred )
55
+
56
+ # Compute the gradients
57
+ gradients = tape .gradient (loss , model .trainable_variables )
58
+ # Apply the gradients to the optimizer
59
+ optimizer .apply_gradients (zip (gradients , model .trainable_variables ))
60
+
61
+ # Project the hidden layer weights to be non-negative
62
+ for layer in model .layers [2 :]:
63
+ if hasattr (layer , 'use_bias' ) and layer .use_bias :
64
+ weights = layer .get_weights ()
65
+ weights [0 ] = np .maximum (weights [0 ], 0 ) # Project weights to be non-negative
66
+ layer .set_weights (weights )
67
+
68
+ # Compute validation loss
69
+ y_val_pred = model (x_val , training = False )
70
+ val_loss = tf .reduce_mean (mse_loss (y_val , y_val_pred ))
71
+
72
+ print (f'Epoch { epoch + 1 } , Validation Loss: { val_loss .numpy ()} ' )
73
+
74
+ # Evaluate the model
75
+ y_val_pred = model (x_val , training = False )
76
+ val_loss = tf .reduce_mean (mse_loss (y_val , y_val_pred ))
77
+ print (f'Final Validation Loss: { val_loss .numpy ()} ' )
78
+
79
+ # Test the model on a new sample
80
+ x_test = np .array ([[0.5 ]])
81
+ y_test = model (x_test )
82
+ print (f'Prediction for { x_test } : { y_test .numpy ()} , Expected: { 2 ** (- x_test )} ' )
83
+
84
+ # Generate data for visualization
85
+ x = np .linspace (- 3 , 3 , 100 )
86
+ y_true = 2 ** (- x )
87
+
88
+ # Compute neural network predictions
89
+ y_pred = model .predict (x .reshape (- 1 , 1 ))
90
+
91
+ # Plot the true function
92
+ plt .plot (x , y_true , label = 'True function: 2^(-x)' )
93
+
94
+ # Plot the neural network approximation
95
+ plt .plot (x , y_pred , label = 'Neural network approximation' )
96
+
97
+ # Add labels and title
98
+ plt .xlabel ('X' )
99
+ plt .ylabel ('Y' )
100
+ plt .title ('True function vs Neural network approximation' )
101
+ plt .legend ()
102
+
103
+ # Show the plot
104
+ plt .show ()
105
+
106
+
107
+ # Iterate through the layers
108
+ for i , layer in enumerate (model .layers ):
109
+ # Print layer name
110
+ print (f"Layer { i } : { layer .name } " )
111
+
112
+ # Get layer parameters
113
+ weights = layer .get_weights ()
114
+
115
+ # Check if layer has parameters
116
+ if weights :
117
+ # Print parameter container sizes
118
+ for w in weights :
119
+ print (f" Parameter shape: { w .shape } " )
120
+ print (f" All non-negative: { tf .reduce_all (tf .greater_equal (w , 0 ))} " )
121
+ else :
122
+ print (" No parameters" )
123
+
124
+ # Print use_bias
125
+ if hasattr (layer , 'use_bias' ):
126
+ print (f" use_bias: { layer .use_bias } " )
127
+ else :
128
+ print (" No use_bias attribute" )
129
+
130
+ import json
131
+ # Extract the weights as matrices
132
+ layer_names = ['FC1' , 'FC2' , 'SKIP2' ]
133
+ weights = {layer_name : model .get_layer (layer_name ).get_weights () for layer_name in layer_names }
134
+
135
+ # Save weights to JSON
136
+ weights_json = {layer_name : [w .tolist () for w in weight_matrices ] for layer_name , weight_matrices in weights .items ()}
137
+ with open ('model_weights.json' , 'w' ) as json_file :
138
+ json .dump (weights_json , json_file )
0 commit comments