73 lines
2.2 KiB
Python
73 lines
2.2 KiB
Python
#use sin cos to get better gradients (than nulayer)
|
|
#migth habe better gradients? (seems that way but not sure yet)
|
|
|
|
#should rename it, but who cares
|
|
#now also able to export the given matrix
|
|
from tensorflow.keras.layers import Layer
|
|
from tensorflow.keras import backend as K
|
|
from tensorflow import keras
|
|
import tensorflow as tf
|
|
|
|
import numpy as np
|
|
|
|
|
|
|
|
class ulayer(Layer):
|
|
def __init__(self,siz,dex1,dex2, **kwargs):
|
|
self.siz = siz
|
|
self.dex1 = dex1
|
|
self.dex2 = dex2
|
|
super(ulayer, self).__init__(**kwargs)
|
|
|
|
def build(self, input_shape):
|
|
# Create a trainable weight variable for this layer.
|
|
self.kernel = self.add_weight(name='kernel',
|
|
shape=(1,),
|
|
initializer=keras.initializers.RandomUniform(-0.5, 0.5),
|
|
trainable=True)
|
|
super(ulayer, self).build(input_shape) # Be sure to call this at the end
|
|
|
|
def numpify(self):
|
|
mat=np.eye(self.siz)
|
|
val=self.weights[0].numpy()[0]
|
|
sin,cos=np.sin(val),np.cos(val)
|
|
mat[self.dex1,self.dex2]=sin
|
|
mat[self.dex2,self.dex1]=-sin
|
|
mat[self.dex1,self.dex1]=cos
|
|
mat[self.dex2,self.dex2]=cos
|
|
return mat
|
|
|
|
|
|
|
|
def call(self, x):
|
|
kernel=self.kernel
|
|
sin=K.sin(kernel)
|
|
cos=K.cos(kernel)
|
|
tan=sin/cos#that should diverge?
|
|
rows=[tf.expand_dims(x[:,i],1) for i in range(self.siz)]
|
|
#instead of ((1,a),(-a,1)), I want this to be
|
|
#((1,a),(-a,1))/sqrt(1+a**2)
|
|
#and with trigonometry, I can get the same result by
|
|
#a=sin(kernel)?
|
|
#multiply to make 1->cos(x) (aka *cos(x))
|
|
#so a actually tan(kernel)
|
|
z1=rows[self.dex2]*tan
|
|
z2=rows[self.dex1]*tan
|
|
rows[self.dex1]+=z1
|
|
rows[self.dex2]-=z2
|
|
rows[self.dex1]*=cos
|
|
rows[self.dex2]*=cos
|
|
rows=K.concatenate(rows,axis=1)
|
|
return rows
|
|
|
|
|
|
mat=tf.eye(self.siz)
|
|
tf.assign(mat[self.dex1,self.dex2],self.kernel)
|
|
#mat[self.dex2,self.dex1]=-self.kernel
|
|
return K.dot(x, mat)
|
|
|
|
def compute_output_shape(self, input_shape):
|
|
return input_shape
|
|
|
|
|