Skip to content

CNN Architecture implementations in Tensorflow #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Nov 7, 2020
Merged

CNN Architecture implementations in Tensorflow #17

merged 9 commits into from
Nov 7, 2020

Conversation

the-robot
Copy link

@the-robot the-robot commented Oct 31, 2020

Your YT contents are awesome!! Especially those CNN architectures from scratch videos. I myself is trying to learn DL and your videos helped me understand the concept better when I was reading the academic papers.

Not very long ago, I started implementing some of the popular CNN architectures with Tensorflow 2.0 in my repo and I think it would be good to PR those to here so the rest can checkout both PyTorch and Tensorflow implementations.

I am not super good with Tensorflow, so if there's something that can be improved, feel free to give comments.

I have implemented

  • AlexNet
  • GoogLeNet / Inception V1
  • LeNet5
  • ResNet
  • VGGNet

@the-robot the-robot changed the title CNN Architectures in Tensorflow CNN Architecture implementations in Tensorflow Oct 31, 2020
@aladdinpersson
Copy link
Owner

aladdinpersson commented Oct 31, 2020

Hey that's awesome @the-robot! I just looked through it rather quickly but I think you could make different VGG types a little bit cleaner perhaps, take a look at my PyTorch implementation:

VGG_types = {
'VGG11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'VGG13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'VGG16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
'VGG19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
}
class VGG_net(nn.Module):
def __init__(self, in_channels=3, num_classes=1000):
super(VGG_net, self).__init__()
self.in_channels = in_channels
self.conv_layers = self.create_conv_layers(VGG_types['VGG16'])
self.fcs = nn.Sequential(
nn.Linear(512*7*7, 4096),
nn.ReLU(),
nn.Dropout(p=0.5),
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Dropout(p=0.5),
nn.Linear(4096, num_classes)
)
def forward(self, x):
x = self.conv_layers(x)
x = x.reshape(x.shape[0], -1)
x = self.fcs(x)
return x
def create_conv_layers(self, architecture):
layers = []
in_channels = self.in_channels
for x in architecture:
if type(x) == int:
out_channels = x
layers += [nn.Conv2d(in_channels=in_channels,out_channels=out_channels,
kernel_size=(3,3), stride=(1,1), padding=(1,1)),
nn.BatchNorm2d(x),
nn.ReLU()]
in_channels = x
elif x == 'M':
layers += [nn.MaxPool2d(kernel_size=(2,2), stride=(2,2))]
return nn.Sequential(*layers)

I think doing something like that with the VGG_types could make it a little more compact

@the-robot
Copy link
Author

the-robot commented Nov 1, 2020

Hey that's awesome @the-robot! I just looked through it rather quickly but I think you could make different VGG types a little bit cleaner perhaps, take a look at my PyTorch implementation:

VGG_types = {
'VGG11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'VGG13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'VGG16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
'VGG19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
}
class VGG_net(nn.Module):
def __init__(self, in_channels=3, num_classes=1000):
super(VGG_net, self).__init__()
self.in_channels = in_channels
self.conv_layers = self.create_conv_layers(VGG_types['VGG16'])
self.fcs = nn.Sequential(
nn.Linear(512*7*7, 4096),
nn.ReLU(),
nn.Dropout(p=0.5),
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Dropout(p=0.5),
nn.Linear(4096, num_classes)
)
def forward(self, x):
x = self.conv_layers(x)
x = x.reshape(x.shape[0], -1)
x = self.fcs(x)
return x
def create_conv_layers(self, architecture):
layers = []
in_channels = self.in_channels
for x in architecture:
if type(x) == int:
out_channels = x
layers += [nn.Conv2d(in_channels=in_channels,out_channels=out_channels,
kernel_size=(3,3), stride=(1,1), padding=(1,1)),
nn.BatchNorm2d(x),
nn.ReLU()]
in_channels = x
elif x == 'M':
layers += [nn.MaxPool2d(kernel_size=(2,2), stride=(2,2))]
return nn.Sequential(*layers)

I think doing something like that with the VGG_types could make it a little more compact

Thanks for the suggestion. Initially I made it that way to group some layers together by following ConvNet config table from original paper. But storing different types in a dictionary would be much cleaner.

I also removed training part and put .summary() to show the model instead.

@aladdinpersson aladdinpersson merged commit 280ad1f into aladdinpersson:master Nov 7, 2020
@aladdinpersson
Copy link
Owner

Added links in the readme, read through the implementations and looked really nice, liked the implementation of ResNet 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants