<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Loading the model.
Here we will focus only on nn.Sequential model types as they are easier to deal with. Generalizing the methods described here to nn.Module will require more work.
Step1:  Accessing the layers
A torch.nn.Sequential module serves itself as an iterable and subscriptable container for all its children modules.
Step2:  Moreover .modules and .children provide generators for accessing layers.
Step3:  Getting the weigths.
Step4:  Getting layer properties
The layer objects themselfs expose most properties as attributes.
<ASSISTANT_TASK:>
Python Code:
class Flatten(nn.Module):
    def forward(self, x):
        return x.view(x.size(0), -1)
    
    def __str__(self):
        return 'Flatten()'
model = nn.Sequential(OrderedDict([
    ('conv2d_1', nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3)),
    ('relu_1', nn.ReLU()),
    ('max_pooling2d_1', nn.MaxPool2d(kernel_size=2)),
    ('conv2d_2', nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3)),
    ('relu_2', nn.ReLU()),
    ('dropout_1', nn.Dropout(p=0.25)),
    ('flatten_1', Flatten()),
    ('dense_1', nn.Linear(3872, 64)),
    ('relu_3', nn.ReLU()),
    ('dropout_2', nn.Dropout(p=0.5)),
    ('dense_2', nn.Linear(64, 10)),
    ('readout', nn.LogSoftmax())
]))
model.load_state_dict(torch.load('example_torch_mnist_model.pth'))
Explanation: Loading the model.
Here we will focus only on nn.Sequential model types as they are easier to deal with. Generalizing the methods described here to nn.Module will require more work.
End of explanation
for i, layer in enumerate(model):
    print('{}\t{}'.format(i, layer))
Explanation: Accessing the layers
A torch.nn.Sequential module serves itself as an iterable and subscriptable container for all its children modules.
End of explanation
for m in model.modules():
    print(m)
for c in model.children():
    print(c)
Explanation: Moreover .modules and .children provide generators for accessing layers.
End of explanation
conv2d_1_weight = model[0].weight.data.numpy()
conv2d_1_weight.shape
for i in range(32):
    plt.imshow(conv2d_1_weight[i, 0])
    plt.show()
Explanation: Getting the weigths.
End of explanation
conv2d_1 = model[0]
conv2d_1.kernel_size
conv2d_1.stride
conv2d_1.dilation
conv2d_1.in_channels, conv2d_1.out_channels
conv2d_1.padding
conv2d_1.output_padding
dropout_1 = model[5]
dropout_1.p
dense_1 = model[7]
dense_1.in_features, dense_1.out_features
Explanation: Getting layer properties
The layer objects themselfs expose most properties as attributes.
End of explanation
<END_TASK>