I have a numpy array like this
array([[[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]],
[[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]]])
shape = (2, 3, 5)
And I want an output which looks like this
output = array([[[1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1.],
[1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1.],
[1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1.]],
[[1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1.],
[1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1.],
[1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1.]]])
Note: The number of zeros to be inserted can vary depending on given factor, in this case the factor was k=3, and the insert is (k-1) which means two zeros will be inserted between numbers. Also given this output I would like to get to the initial input
You can use numpy.zeros to initialize an output array of the desired shape, then indexing to fill the values:
k = 3
shape = a.shape
output = np.zeros(shape[:-1]+((shape[-1]-1)*k+1,))
output[...,::k] = a
output:
array([[[1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1.],
[1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1.],
[1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1.]],
[[1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1.],
[1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1.],
[1., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 0., 1.]]])
I have been using Gaussian Mixture Models (GMM) to model a set of peaks in a 2D numpy array (a).
a = np.array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 1., 100., 1000., 100., 2., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 1., 1., 1., 1., 1., 1., 1., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 0., 1., 1., 100., 100., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 2., 1., 2., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 1., 1., 1., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 1., 1., 0., 0.],
[0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
The problem is that in order to fit a GMM to my data with sklearn I have to first generate a density_array, which holds a huge amount of data points depending on the height of the peaks in a.
def convert_to_density_array(array):
"""
Convert an array to a density array
"""
density_list = []
# iterate over each i,j coordinate in the array
for (i, j), value in np.ndenumerate(array):
for x in range(int(value)):
density_list.append((i, j))
return np.array(density_list)
density_array = convert_to_density_array(a)
gmm = mixture.GaussianMixture(n_components=2,covariance_type='full').fit(density_array)
Is there an efficient way of representing a 2D numpy array for the purpose of fitting a GMM to it?
you can store data using less precision by adding dtype=np.float32 to your np.array call, which is okay as long as you are fine with 8 digits of precision instead of 15 (which is totally acceptable in your case), but that's the only way to store the same data in memory in less footprint and still pass it to gmm.
what you are trying to do is curve fitting, not data modelling , so you can use scipy curve fit on your original data without making density_array to start with, you just have to pass it a function of two gaussians and in a loop change the initial estimate randomly until you get the least error, but as writing the code for it will take some time, consider this approach only if you cannot get your data in memory using any other method.
I would like to create a dense Layer that has weights non trainable, so fixed, and i write the function like this:
output_layer_subclass = Dense(classes2_num, activation='softmax',name='classification_subclasses')(b1)
output_layer_class=Dense(M.shape[0], trainable=False, weights=[M], use_bias=False,activation='softmax',name='classification_classes')(output_layer_subclass)
where b1 is a Flatten layer. Anyway the M matrix has shape 5x97 and the classes2_num is 97.
M is a matrix made of zeros and ones.
If I try like this I receive this error when create the model:
Layer weight shape (97, 5) not compatible with provided weight shape (5, 97)
Of course if I transpose the M everything works but the important part is that M matrix has to remain with 5x97 shape.
How can I do?
Thanks,
I' m really new to this world hope one day could help the community too.
Edit:
I have tried like:
output_layer_subclass = Dense(classes2_num, activation='softmax',name='classification_subclasses')(b1)
output_layer_subclass = Lambda(lambda x: K.dot(M,K.transpose(x)))(output_layer_subclass)
output_layer_class=Dense(classes_num, trainable=False, use_bias=False,activation='softmax',name='classification_classes')(output_layer_subclass)
model = Model(inputs=input_layer, outputs=[output_layer_subclass,output_layer_class])
I receive this error when I run
AttributeError: 'tuple' object has no attribute 'rank'
Update:
M is a sparse Matrix of zeros and ones... like
array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1.]])
I've used the tf.keras.backend.batch_dot method inside a Lambda layer. Hope it helps:
import numpy as np
import tensorflow as tf
classes2_num = 97
classes_num = 10
M = np.array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1.]]).astype(np.float32)
M = np.expand_dims(M, axis=0)
K = tf.keras.backend
inputs = tf.keras.Input(shape=(100,))
output_layer_subclass = tf.keras.layers.Dense(classes2_num, activation='softmax',name='classification_subclasses')(inputs)
output_layer_subclass = tf.keras.layers.Lambda(lambda x: K.batch_dot(M, x))(output_layer_subclass)
output_layer_class= tf.keras.layers.Dense(classes_num, trainable=False, use_bias=False,activation='softmax',name='classification_classes')(output_layer_subclass)
model = tf.keras.Model(inputs=inputs, outputs=[output_layer_subclass,output_layer_class])
I'm trying to append to an existing dataframe 3 new columns which should encode dummy variables.
To do this I am creating a function to look through the array to be "dummied", and for each 'hit' to assign the corresponding value to the to a new row.
import numpy as np
import pandas as pd
iriss = np.concatenate((np.array(['setosa']*50), np.array(['versicolor']*50), np.array(['virginica']*50)), axis = 0)
In this case I present the Iris data set's species column, with 150 equally distributed species (50 units per species).
def one_hot_coding():
one_hot_column = np.array([], dtype = 'int8')
for one_hot in iriss:
#my idea here is to find the 'hit = species' and to then for each 'hit' to assign to these
# three different np.arrays the value of one or zero
if one_hot == 'setosa':
one_hot_setosa = np.append(one_hot_column, 1)
one_hot_versicolor = np.append(one_hot_column, 0)
one_hot_virginica = np.append(one_hot_column, 0)
elif one_hot == 'versicolor':
one_hot_setosa = np.append(one_hot_column, 0)
one_hot_versicolor = np.append(one_hot_column, 1)
one_hot_virginica = np.append(one_hot_column, 0)
else:
one_hot_setosa = np.append(one_hot_column, 0)
one_hot_versicolor = np.append(one_hot_column, 0)
one_hot_virginica = np.append(one_hot_column, 1)
one_hot_setosa = np.concatenate((one_hot_setosa), axis = 0)
print(one_hot_setosa)
one_hot_coding()
Results Discussion:
to make it easier I will only talk about one_hot_setosa:
when I call print on one_hot_setosa 150 lines appear where the first 50 lines are [1]'s and the latter 100 [0]'s.
[1] [1] ...48 [0] [0] ...48 [0] [0] ... 48
From what I see here my results are 150 independent arrays inside of the array called one_hot_setosa.
When I try to concatenate them all to obtain a single array (i.e. the iriss array created to house the 150 units) I get the following error
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-107-6f70367ed6eb> in <module>
24
25 print(one_hot_setosa)
---> 26 one_hot_coding()
<ipython-input-107-6f70367ed6eb> in one_hot_coding()
21 one_hot_virginica = np.append(one_hot_column, 1)
22
---> 23 one_hot_setosa = np.concatenate((one_hot_setosa), axis = 0)
24
25 print(one_hot_setosa)
<__array_function__ internals> in concatenate(*args, **kwargs)
ValueError: zero-dimensional arrays cannot be concatenated
So this error is telling me that I don't actually have 150 arrays, or better said an array.shape = (150, 1) (which is what I want). but that actually my array contains nothing? Why is this?
Okay, so I've been fighting a lot but I managed to solve the problem.
np.concatenate will add rows to the array. So I specified I wanted to add rows to the one_hot_flower. Also, as #hpaulj pointed out, square brackets are very important to consider. Since my arrays are 1d arrays I needed to add only square brackets once to the value I wanted to concatenate.
All in all the final code looks like this:
import numpy as np
import pandas as pd
iriss = np.concatenate((np.array(['setosa']*50), np.array(['versicolor']*50), np.array(['virginica']*50)), axis = 0)
one_hot_setosa = np.array([])
one_hot_versicolor = np.array([])
one_hot_virginica = np.array([])
def one_hot_coding():
global one_hot_setosa
global one_hot_versicolor
global one_hot_virginica
for one_hot in iriss:
if one_hot == 'setosa':
one_hot_setosa = np.concatenate((one_hot_setosa, np.array([1])), axis = 0)
one_hot_versicolor = np.concatenate((one_hot_versicolor, np.array([0])), axis = 0)
one_hot_virginica = np.concatenate((one_hot_virginica, np.array([0])), axis = 0)
elif one_hot == 'versicolor':
one_hot_setosa = np.concatenate((one_hot_setosa, np.array([0])), axis = 0)
one_hot_versicolor = np.concatenate((one_hot_versicolor, np.array([1])), axis = 0)
one_hot_virginica = np.concatenate((one_hot_virginica, np.array([0])), axis = 0)
else:
one_hot_setosa = np.concatenate((one_hot_setosa, np.array([0])), axis = 0)
one_hot_versicolor = np.concatenate((one_hot_versicolor, np.array([0])), axis = 0)
one_hot_virginica = np.concatenate((one_hot_virginica, np.array([1])), axis = 0)
#one_hot_setosa = np.concatenate((one_hot_setosa), axis = 0)
return one_hot_setosa, one_hot_versicolor, one_hot_virginica
one_hot_coding()
[Out]:
(array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]),
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]),
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]))