I am trying to implement scikit-learn's PolynomialFeatures as a layer in a feedforward neural network in tensorflow and Keras. I'll give an example using NumPy arrays for the sake of simplicity. If a batch has three samples and the activations of a certain layer are equal to the (3, 2)-shaped matrix
>>> X = np.arange(0, 6).reshape(2, 3)
>>> X
array([[0, 1],
[2, 3],
[4, 5]])
then I would like the activations in the next layer to be equal to a degree-2 polynomial feature expansion of X:
>>> from sklearn.preprocessing import PolynomialFeatures
>>> PolynomialFeatures(degree=2).fit_transform(X)
array([[ 1., 0., 1., 0., 0., 1.],
[ 1., 2., 3., 4., 6., 9.],
[ 1., 4., 5., 16., 20., 25.]])
That is, if the activations of layer i are the matrix X (of shape (batch_size, num_features)), then for the parameter choice degree=2 I would like the activations of layer i + 1 to be a concatenation of
- a column of
batch_sizemany1.'s, Xitself,- and element-wise products of all unordered pairs of the columns of
X:X[:, 0] * X[:, 0],X[:, 0] * X[:, 1], andX[:, 1] * X[:, 1].
My closest solution so far is to concatenate some powers of X:
import keras.backend as K
X = K.reshape(K.arange(0, 6), (3, 2))
with K.get_session().as_default():
print(K.concatenate([K.pow(X, 0), K.pow(X, 1), K.pow(X, 2)]).eval())
Output:
[[ 1 1 0 1 0 1]
[ 1 1 2 3 4 9]
[ 1 1 4 5 16 25]]
i.e., a concatenation of two columns of 1s (one more than I'd like, but I can live with this duplication), X itself, and X squared element-wise.
Is there a way to compute products of different columns (in an automatically differentiable way)? The step of PolynomialFeatures that I cannot figure out how to implement in tensorflow is to fill in a column of a matrix with the product (across axis=1) of certain columns of another matrix: XP[:, i] = X[:, c].prod(axis=1), where c is a tuple of indices such as (0, 0, 1).