Custom kernels values pytorch

username: jasg
cooked: <p>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]<br>
This apperar in :       y_pred = CNNmodel(X_train)</p>
<p>How can I customize the kernel values ​​in this code please</p>
<pre><code class="lang-python">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}%')
</code></pre>

username: ptrblck
cooked: <p>Your kernel shape in <code>kn</code> is wrong, as <code>nn.Conv2d</code> uses a <code>weight</code> with the shape <code>[out_channels, in_channels, height, width]</code>.</p>
<p>This code should work:</p>
<pre><code class="lang-python">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)
</code></pre>
<p>PS: I’ve formatted your post for easier debugging. You can add code snippets by wrapping them in three backticks ``` <img src="https://discuss.pytorch.org/images/emoji/apple/wink.png?v=9" title=":wink:" class="emoji" alt=":wink:"></p>

username: jasg
cooked: <p>Thanks but appear other error:     p.data.addcdiv_(-step_size, exp_avg, denom)<br>
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.</p>
<p>This is code final with change</p>
<pre><code class="lang-auto">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}%')</code></pre>

username: jasg
cooked: <p>Thanks but appear other error: p.data.addcdiv_(-step_size, exp_avg, denom)<br>
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.</p>
<p>This is code final with change</p>
<pre><code class="lang-auto">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}%')</code></pre>

username: ptrblck
cooked: <p>This error is raised due to the <code>expand</code> call in <code>kn</code>, if you want to calculate gradients for the kernels.<br>
You could use <code>repeat</code> instead or call <code>.contiguous()</code> on <code>kn</code>:</p>
<pre><code class="lang-python">conv1.weight = nn.Parameter(kn.expand(6, 3, -1, -1).contiguous())
</code></pre>

username: jasg
cooked: <p>Thanks, you are a doctor in these subjects…!!!</p>

username: jasg
cooked: <p>one question: What type of kernel does the algorithm use? I have seen some articles that talk about gausian blur… is correct???</p>

username: ptrblck
cooked: <p>Your kernel is corresponding to a <a href="https://en.wikipedia.org/wiki/Sobel_operator">Sobel operator</a> (in the x-axis), which is used for edge detection.</p>

username: jasg
cooked: <p>assuming I don’t enter any kernel arrays and let the pytorch do as the pytorch chooses, what type of kernel do you choose</p>

username: ptrblck
cooked: <p>PyTorch modules use the <code>reset_parameters</code> model to randomly initialize all parameters.<br>
For conv layers <a href="https://github.com/pytorch/pytorch/blob/459163b8ebdcecebfe15443f7cd9f6f9a23c9dca/torch/nn/modules/conv.py#L55-L60">this code snippet</a> is used.</p>

username: jasg
cooked: <p>sorry these random kernel matrices are different from known matrices according to: https: <a href="//setosa.io/ev/image-kernels/" rel="nofollow noopener">//setosa.io/ev/image-kernels/</a></p>

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

username: jasg
cooked: <p>that other functions can use apart nn.Linear and log_softmax in  the class ConvolutionalNetwork<br>
How to configure in this function:</p>
<pre><code class="lang-auto">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)</code></pre>