thesoens/n2ulayer.py

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