CNN: Reshaping CSV data for Conv1d in a Binary Classification Problem

Dear All,
I created a minimal example here to reproduce the problem I am facing.
I have a data set with 21 features (e.g covariates) and 108405 rows, e.g.:
torch.Size([108405, 21])
I am interested in using a CNN, for this problem and I have the following NN architecture:

Net2 (
  (l1): Sequential (
    (0): Linear (21 -> 126)
    (1): Dropout (p = 0.15)
    (2): LeakyReLU (0.1)
    (3): BatchNorm1d(126, eps=1e-05, momentum=0.1, affine=True)
  )
  (c1): Sequential (
    (0): Conv1d(21, 126, kernel_size=(3,), stride=(1,), padding=(1,))
    (1): Dropout (p = 0.25)
    (2): LeakyReLU (0.1)
    (3): BatchNorm1d(126, eps=1e-05, momentum=0.1, affine=True)
  )
  (out): Sequential (
    (0): Linear (756 -> 1)
  )
  (sig): Sigmoid ()
)

Now, I would like to eliminate the first Linear (21 -> 126) layer:

The only reason it is there is because I was unable to correctly shape my input to feed directly into the CNN that follows, e.g.:

Is this possible? How can I reshape my x_tensor so that I t can be fed directly into the Conv1d layer?

This is the full network:

# References:
# https://github.com/vinhkhuc/PyTorch-Mini-Tutorials/blob/master/5_convolutional_net.py
# https://gist.github.com/spro/c87cc706625b8a54e604fb1024106556

X_tensor_train= XnumpyToTensor(trainX) # default order is NBC for a 3d tensor, but we have a 2d tensor
X_shape=X_tensor_train.data.size()

# Dimensions
# Number of features for the input layer
N_FEATURES=trainX.shape[1]
# Number of rows
NUM_ROWS_TRAINNING=trainX.shape[0]
# this number has no meaning except for being divisable by 2
N_MULT_FACTOR=6 # min should be 4
# Size of first linear layer
N_HIDDEN=N_FEATURES * N_MULT_FACTOR
# CNN kernel size
N_CNN_KERNEL=3


DEBUG_ON=True
def debug(msg, x):
    if DEBUG_ON:
        print (msg + ', (size():' + str (x.size()))
    
class Net2(nn.Module):    
    def __init__(self, n_feature, n_hidden, n_output, n_cnn_kernel, n_mult_factor=N_MULT_FACTOR):
        super(Net2, self).__init__()
        self.n_feature=n_feature
        self.n_hidden=n_hidden
        self.n_output= n_output 
        self.n_cnn_kernel=n_cnn_kernel
        self.n_mult_factor=n_mult_factor
        self.n_l2_hidden=self.n_hidden * (self.n_mult_factor - self.n_cnn_kernel + 3)
                        
        self.l1 = nn.Sequential(
            torch.nn.Linear(self.n_feature, self.n_hidden),
            torch.nn.Dropout(p=1 -.85),            
            torch.nn.LeakyReLU (0.1),            
            torch.nn.BatchNorm1d(self.n_hidden, eps=1e-05, momentum=0.1, affine=True)            
        )       
        
        self.c1= nn.Sequential(            
            torch.nn.Conv1d(self.n_feature, self.n_hidden, 
                            kernel_size=(self.n_cnn_kernel,), stride=(1,), padding=(1,)),
            torch.nn.Dropout(p=1 -.75),            
            torch.nn.LeakyReLU (0.1),
            torch.nn.BatchNorm1d(self.n_hidden, eps=1e-05, momentum=0.1, affine=True)        
        )                        
        self.out = nn.Sequential(
            torch.nn.Linear(self.n_l2_hidden,
                            self.n_output),  
        )                
        self.sig=nn.Sigmoid()

        
    def forward(self, x):
        debug('raw',x)   
        varSize=x.data.shape[0] # must be calculated here in forward() since its is a dynamic size        
        x=self.l1(x)                
        debug('after lin',x)                   
        # for CNN        
        x = x.view(varSize,self.n_feature,self.n_mult_factor)
        debug('after view',x)   
        x=self.c1(x)
        debug('after CNN',x)   
        # for Linear layer
        x = x.view(varSize, self.n_hidden * (self.n_mult_factor -self.n_cnn_kernel + 3))
        debug('after 2nd view',x)          
#         x=self.l2(x)                    
        x=self.out(x)   
        debug('after self.out',x)   
        x=self.sig(x)
        return x
    
net = Net2(n_feature=N_FEATURES, n_hidden=N_HIDDEN, n_output=1, n_cnn_kernel=N_CNN_KERNEL)  
if use_cuda:
    net=net.cuda() 
lgr.info(net)
b = net(X_tensor_train)
print ('(b.size():' + str (b.size())) 

Output:

(108405, 21)
<type 'numpy.ndarray'>
<class 'torch.cuda.FloatTensor'>
torch.Size([108405, 21])
raw, (size():torch.Size([108405, 21])
after lin, (size():torch.Size([108405, 126])
after view, (size():torch.Size([108405, 21, 6])
after CNN, (size():torch.Size([108405, 126, 6])
after 2nd view, (size():torch.Size([108405, 756])
after self.out, (size():torch.Size([108405, 1])
(b.size():torch.Size([108405, 1])

Many thanks,

I was able to resolve this (will upload a new version), but would greatly appreciate someone taking a look at the code.

Well … the party was too early, whenever I set N_CNN_KERNEL to anything other than 3, I get a dimension mismatch error.

Anyone …?
Thanks,