Custom kernels values pytorch

Friends I get this error:RuntimeError: expected stride to be a single integer value or a list of 1 values to match the convolution dimensions, but got stride=[1, 1]
This apperar in : y_pred = CNNmodel(X_train)

How can I customize the kernel values ​​in this code please

kn = torch.Tensor([[1 ,0, -1],[2, 0 ,-2], [1, 0 ,-1]]).unsqueeze(0)
kn = torch.nn.Parameter( kn ) # calling this turns tensor into "weight" parameter

class ConvolutionalNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3,6,kernel_size=(3,3), stride=1, padding=1, bias=False)
        self.conv1.weight=kn
        self.conv2 = nn.Conv2d(6, 16, kernel_size=(3,3), stride=1, padding=1, bias=False)
        self.conv2.weight=kn
        self.fc1 = nn.Linear(56*56*16, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 18)

def forward(self, X):
        X = F.relu(self.conv1(X))
        X = F.max_pool2d(X, 2, 2)#max pooling de 2x2
        X = F.relu(self.conv2(X))
        X = F.max_pool2d(X, 2, 2)
        X = X.view(-1, 56*56*16)
        X = F.relu(self.fc1(X))
        X = F.relu(self.fc2(X))
        X = self.fc3(X)
        return F.log_softmax(X, dim=1)
torch.manual_seed(101)
CNNmodel = ConvolutionalNetwork()


epochs = 20

for i in range(epochs):
    trn_corr = 0
    tst_corr = 0
    
    for b, (X_train, y_train) in enumerate(train_loader):
        
        if b == max_trn_batch:
            break
        b+=1
        
        y_pred = CNNmodel(X_train)
        loss = criterion(y_pred, y_train)
 
        predicted = torch.max(y_pred.data, 1)[1]
        batch_corr = (predicted == y_train).sum()
        trn_corr += batch_corr
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        # Print interim results
        if b%200 == 0:
            print(f'epoch: {i:2}  batch: {b:4} [{10*b:6}/8000]  loss: {loss.item():10.8f}  \
accuracy: {trn_corr.item()*100/(10*b):7.3f}%')

Your kernel shape in kn is wrong, as nn.Conv2d uses a weight with the shape [out_channels, in_channels, height, width].

This code should work:

kn = torch.Tensor([[1 ,0, -1],[2, 0 ,-2], [1, 0 ,-1]]).unsqueeze(0).unsqueeze(0)

class ConvolutionalNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3,6,kernel_size=(3,3), stride=1, padding=1, bias=False)
        self.conv1.weight = nn.Parameter(kn.expand(6, 3, -1, -1))
        self.conv2 = nn.Conv2d(6, 16, kernel_size=(3,3), stride=1, padding=1, bias=False)
        self.conv2.weight = nn.Parameter(kn.expand(16, 6, -1, -1))
        self.fc1 = nn.Linear(56*56*16, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 18)
    
    def forward(self, X):
            X = F.relu(self.conv1(X))
            X = F.max_pool2d(X, 2, 2)#max pooling de 2x2
            X = F.relu(self.conv2(X))
            X = F.max_pool2d(X, 2, 2)
            X = X.view(-1, 56*56*16)
            X = F.relu(self.fc1(X))
            X = F.relu(self.fc2(X))
            X = self.fc3(X)
            return F.log_softmax(X, dim=1)
torch.manual_seed(101)
CNNmodel = ConvolutionalNetwork()

x = torch.randn(1, 3, 224, 224,)
out = CNNmodel(x)

PS: I’ve formatted your post for easier debugging. You can add code snippets by wrapping them in three backticks ``` :wink:

Thanks but appear other error: p.data.addcdiv_(-step_size, exp_avg, denom)
RuntimeError: unsupported operation: more than one element of the written-to tensor refers to a single memory location. Please clone() the tensor before performing the operation.

This is code final with change

import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import DataLoader
from torchvision import datasets, transforms # add models to the list
import os
import seaborn as sn  # for heatmaps
from sklearn.metrics import confusion_matrix
from sklearn import metrics 

import numpy as np
import matplotlib.pyplot as plt
import cv2
import pandas as pd

# ignore harmless warnings
import warnings
warnings.filterwarnings("ignore")

root = '../'

###los transform es el tratamiento previo de las imagenes por ejemplo la imagen ingresa con
## 480x640 pixeles y lo redimenziona a 240x240 pixeles
train_transform = transforms.Compose([
        transforms.RandomRotation(10),      # rotate +/- 10 degrees
        transforms.RandomHorizontalFlip(),  # reverse 50% of images
        transforms.Resize(224),             # resize shortest side to 224 pixels
        transforms.CenterCrop(224),         # crop longest side to 224 pixels at center
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ])

test_transform = transforms.Compose([
        transforms.Resize(224),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ])
train_data = datasets.ImageFolder(os.path.join(root, 'train'), transform=train_transform)
test_data = datasets.ImageFolder(os.path.join(root, 'validation'), transform=test_transform)

torch.manual_seed(42)

#los loaders sirven para cargar de poco a poco las imagenes en la memoria con 
#10 imagenes en paralelo, es decir una imagen por cada clase o carpeta del total 
#de imagenes es procesada en paralelo
train_loader = DataLoader(train_data, batch_size=10, shuffle=True)
test_loader = DataLoader(test_data, batch_size=10, shuffle=True)

#obtiene los labels o clases del dataset
class_names = train_data.classes

print(class_names)
print(f'Training images available: {len(train_data)}')
print(f'Testing images available:  {len(test_data)}')

# Inverse normalize the images, esto se hace cuando la imagen es transformada al principio
inv_normalize = transforms.Normalize(
    mean=[-0.485/0.229, -0.456/0.224, -0.406/0.225],
    std=[1/0.229, 1/0.224, 1/0.225]
)

kn = torch.Tensor([[1 ,0, -1],[2, 0 ,-2], [1, 0 ,-1]]).unsqueeze(0).unsqueeze(0)

class ConvolutionalNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3,6,kernel_size=(3,3), stride=1, padding=1, bias=False)
        self.conv1.weight = nn.Parameter(kn.expand(6, 3, -1, -1))
        self.conv2 = nn.Conv2d(6, 16, kernel_size=(3,3), stride=1, padding=1, bias=False)
        self.conv2.weight = nn.Parameter(kn.expand(16, 6, -1, -1))
        self.fc1 = nn.Linear(56*56*16, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 18)
    
    def forward(self, X):
            X = F.relu(self.conv1(X))
            X = F.max_pool2d(X, 2, 2)#max pooling de 2x2
            X = F.relu(self.conv2(X))
            X = F.max_pool2d(X, 2, 2)
            X = X.view(-1, 56*56*16)
            X = F.relu(self.fc1(X))
            X = F.relu(self.fc2(X))
            X = self.fc3(X)
            return F.log_softmax(X, dim=1)
torch.manual_seed(101)
CNNmodel = ConvolutionalNetwork()

x = torch.randn(1, 3, 224, 224,)
out = CNNmodel(x)

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(CNNmodel.parameters(), lr=0.001)
print(CNNmodel)

import time
start_time = time.time()

epochs = 20

max_trn_batch = 800
max_tst_batch = 300

train_losses = []
test_losses = []
train_correct = []
test_correct = []

for i in range(epochs):
    trn_corr = 0
    tst_corr = 0
    
    # Run the training batches
    for b, (X_train, y_train) in enumerate(train_loader):
        
        # Limit the number of batches
        if b == max_trn_batch:
            break
        b+=1
        
        # Apply the model
        y_pred = CNNmodel(X_train)
        loss = criterion(y_pred, y_train)
 
        # Tally the number of correct predictions
        predicted = torch.max(y_pred.data, 1)[1]
        batch_corr = (predicted == y_train).sum()
        trn_corr += batch_corr
        
        # Update parameters
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        # Print interim results
        if b%200 == 0:
            print(f'epoch: {i:2}  batch: {b:4} [{10*b:6}/8000]  loss: {loss.item():10.8f}  \
accuracy: {trn_corr.item()*100/(10*b):7.3f}%')

    train_losses.append(loss)
    train_correct.append(trn_corr)

    # Run the testing batches
    with torch.no_grad():
        for b, (X_test, y_test) in enumerate(test_loader):
            # Limit the number of batches
            if b == max_tst_batch:
                break

            # Apply the model
            y_val = CNNmodel(X_test)

            # Tally the number of correct predictions
            predicted = torch.max(y_val.data, 1)[1] 
            tst_corr += (predicted == y_test).sum()

    loss = criterion(y_val, y_test)
    test_losses.append(loss)
    test_correct.append(tst_corr)

print(f'\nDuration: {time.time() - start_time:.0f} seconds') # print the time elapsed
torch.save(CNNmodel.state_dict(), 'quinua_pytorch.pt')
print(test_correct)
print(f'Test accuracy: {test_correct[-1].item()*100/3000:.3f}%')

Thanks but appear other error: p.data.addcdiv_(-step_size, exp_avg, denom)
RuntimeError: unsupported operation: more than one element of the written-to tensor refers to a single memory location. Please clone() the tensor before performing the operation.

This is code final with change

import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import DataLoader
from torchvision import datasets, transforms # add models to the list
import os
import seaborn as sn  # for heatmaps
from sklearn.metrics import confusion_matrix
from sklearn import metrics 

import numpy as np
import matplotlib.pyplot as plt
import cv2
import pandas as pd

# ignore harmless warnings
import warnings
warnings.filterwarnings("ignore")

root = '../'

###los transform es el tratamiento previo de las imagenes por ejemplo la imagen ingresa con
## 480x640 pixeles y lo redimenziona a 240x240 pixeles
train_transform = transforms.Compose([
        transforms.RandomRotation(10),      # rotate +/- 10 degrees
        transforms.RandomHorizontalFlip(),  # reverse 50% of images
        transforms.Resize(224),             # resize shortest side to 224 pixels
        transforms.CenterCrop(224),         # crop longest side to 224 pixels at center
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ])

test_transform = transforms.Compose([
        transforms.Resize(224),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ])
train_data = datasets.ImageFolder(os.path.join(root, 'train'), transform=train_transform)
test_data = datasets.ImageFolder(os.path.join(root, 'validation'), transform=test_transform)

torch.manual_seed(42)

#los loaders sirven para cargar de poco a poco las imagenes en la memoria con 
#10 imagenes en paralelo, es decir una imagen por cada clase o carpeta del total 
#de imagenes es procesada en paralelo
train_loader = DataLoader(train_data, batch_size=10, shuffle=True)
test_loader = DataLoader(test_data, batch_size=10, shuffle=True)

#obtiene los labels o clases del dataset
class_names = train_data.classes

print(class_names)
print(f'Training images available: {len(train_data)}')
print(f'Testing images available:  {len(test_data)}')

# Inverse normalize the images, esto se hace cuando la imagen es transformada al principio
inv_normalize = transforms.Normalize(
    mean=[-0.485/0.229, -0.456/0.224, -0.406/0.225],
    std=[1/0.229, 1/0.224, 1/0.225]
)

kn = torch.Tensor([[1 ,0, -1],[2, 0 ,-2], [1, 0 ,-1]]).unsqueeze(0).unsqueeze(0)

class ConvolutionalNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3,6,kernel_size=(3,3), stride=1, padding=1, bias=False)
        self.conv1.weight = nn.Parameter(kn.expand(6, 3, -1, -1))
        self.conv2 = nn.Conv2d(6, 16, kernel_size=(3,3), stride=1, padding=1, bias=False)
        self.conv2.weight = nn.Parameter(kn.expand(16, 6, -1, -1))
        self.fc1 = nn.Linear(56*56*16, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 18)
    
    def forward(self, X):
            X = F.relu(self.conv1(X))
            X = F.max_pool2d(X, 2, 2)#max pooling de 2x2
            X = F.relu(self.conv2(X))
            X = F.max_pool2d(X, 2, 2)
            X = X.view(-1, 56*56*16)
            X = F.relu(self.fc1(X))
            X = F.relu(self.fc2(X))
            X = self.fc3(X)
            return F.log_softmax(X, dim=1)
torch.manual_seed(101)
CNNmodel = ConvolutionalNetwork()

x = torch.randn(1, 3, 224, 224,)
out = CNNmodel(x)

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(CNNmodel.parameters(), lr=0.001)
print(CNNmodel)

import time
start_time = time.time()

epochs = 20

max_trn_batch = 800
max_tst_batch = 300

train_losses = []
test_losses = []
train_correct = []
test_correct = []

for i in range(epochs):
    trn_corr = 0
    tst_corr = 0
    
    # Run the training batches
    for b, (X_train, y_train) in enumerate(train_loader):
        
        # Limit the number of batches
        if b == max_trn_batch:
            break
        b+=1
        
        # Apply the model
        y_pred = CNNmodel(X_train)
        loss = criterion(y_pred, y_train)
 
        # Tally the number of correct predictions
        predicted = torch.max(y_pred.data, 1)[1]
        batch_corr = (predicted == y_train).sum()
        trn_corr += batch_corr
        
        # Update parameters
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        # Print interim results
        if b%200 == 0:
            print(f'epoch: {i:2}  batch: {b:4} [{10*b:6}/8000]  loss: {loss.item():10.8f}  \
accuracy: {trn_corr.item()*100/(10*b):7.3f}%')

    train_losses.append(loss)
    train_correct.append(trn_corr)

    # Run the testing batches
    with torch.no_grad():
        for b, (X_test, y_test) in enumerate(test_loader):
            # Limit the number of batches
            if b == max_tst_batch:
                break

            # Apply the model
            y_val = CNNmodel(X_test)

            # Tally the number of correct predictions
            predicted = torch.max(y_val.data, 1)[1] 
            tst_corr += (predicted == y_test).sum()

    loss = criterion(y_val, y_test)
    test_losses.append(loss)
    test_correct.append(tst_corr)

print(f'\nDuration: {time.time() - start_time:.0f} seconds') # print the time elapsed
torch.save(CNNmodel.state_dict(), 'quinua_pytorch.pt')
print(test_correct)
print(f'Test accuracy: {test_correct[-1].item()*100/3000:.3f}%')

This error is raised due to the expand call in kn, if you want to calculate gradients for the kernels.
You could use repeat instead or call .contiguous() on kn:

conv1.weight = nn.Parameter(kn.expand(6, 3, -1, -1).contiguous())

Thanks, you are a doctor in these subjects…!!!

1 Like

one question: What type of kernel does the algorithm use? I have seen some articles that talk about gausian blur… is correct???

Your kernel is corresponding to a Sobel operator (in the x-axis), which is used for edge detection.

assuming I don’t enter any kernel arrays and let the pytorch do as the pytorch chooses, what type of kernel do you choose

PyTorch modules use the reset_parameters model to randomly initialize all parameters.
For conv layers this code snippet is used.

sorry these random kernel matrices are different from known matrices according to: https: //setosa.io/ev/image-kernels/

Yes, since the model is randomly initialized at the beginning and trained afterwards.
Through the training you might get some edge detectors etc. in the first layers.
In CNNs you usually don’t initialize the filters to known image processing kernels, but let the model train them.

that other functions can use apart nn.Linear and log_softmax in the class ConvolutionalNetwork
How to configure in this function:

class ConvolutionalNetwork(nn.Module):
        def __init__(self):
            super().__init__()
            self.conv1 = nn.Conv2d(tipo_image, 6, kernel_size=(kernel,kernel), stride=stridee,padding=paddingg,bias=biass)
            self.conv2 = nn.Conv2d(6, 16, kernel_size=(kernel,kernel), stride=stridee,padding=paddingg,bias=biass)
            self.conv3 = nn.Conv2d(16, 32, kernel_size=(kernel,kernel), stride=stridee,padding=paddingg,bias=biass)

        
            self.fc1 = nn.Linear(f*f*32, 120)
            self.fc2 = nn.Linear(120, 84)
            self.fc3 = nn.Linear(84, 18)

        def forward(self, X):
            X = F.relu(self.conv1(X))
            X = F.max_pool2d(X, 2, 2)
            X = F.relu(self.conv2(X))
            X = F.max_pool2d(X, 2, 2)
            X = F.relu(self.conv3(X))
            X = F.max_pool2d(X, 2, 2)
            X = X.view(-1, f*f*32)
            X = F.relu(self.fc1(X))
            X = F.relu(self.fc2(X))
            X = self.fc3(X)
            return F.log_softmax(X, dim=1)
    torch.manual_seed(101)
    CNNmodel = ConvolutionalNetwork()
    criterion = nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(CNNmodel.parameters(), lr=0.001)
    print(CNNmodel)