'construct a convolutional neural network with Resnet-style skip connections.
Arguments are the same as with the default CNNPolicy network, except the default
number of layers is 20 plus a new n_skip parameter
Keword Arguments:
- input_dim:             depth of features to be processed by first layer (no default)
- board:                 width of the go board to be processed (default 19)
- filters_per_layer:     number of filters used on every layer (default 128)
- layers:                number of convolutional steps (default 20)
- filter_width_K:        (where K is between 1 and <layers>) width of filter on
layer K (default 3 except 1st layer which defaults to 5).
Must be odd.
- n_skip_K:             (where K is as in filter_width_K) number of convolutional
layers to skip with the linear path starting at K. Only valid
at K >= 1. (Each layer defaults to 1)
Note that n_skip_1=s means that the next valid value of n_skip_* is 3
A diagram may help explain (numbers indicate layer):
1        2        3           4        5        6
I--C--B--R--C--B--R--C--M--B--R--C--B--R--C--B--R--C--M  ...  M --R--F--O
[n_skip_1 = 2]          [n_skip_3 = 3]
I - input
B - BatchNormalization
R - ReLU
C - Conv2D
F - Flatten
O - output
M - merge
The input is always passed through a Conv2D layer, the output of which
layer is counted as \'1\'.  Each subsequent [R -- C] block is counted as
one \'layer\'. The \'merge\' layer isn\'t counted; hence if n_skip_1 is 2,
the next valid skip parameter is n_skip_3, which will start at the
output of the merge'

@staticmethod
def create_network(**kwargs):

    defaults = {'board': 19, 'filters_per_layer': 128, 'layers': 20, 'filter_width_1': 5}
    params = defaults
    params.update(kwargs)
    model_input = Input(shape=(params['input_dim'], params['board'], params['board']))
    convolution_path = convolutional.Convolution2D(input_shape=(), nb_filter=params['filters_per_layer'], nb_row=params['filter_width_1'], nb_col=params['filter_width_1'], init='uniform', activation='linear', border_mode='same')(model_input)
    def add_resnet_unit(path, K, **params):
        "Add    a    resnet    unit    to    path    starting    at    layer    'K',\n                                                adding    as    many    (ReLU    +    Conv2D)    modules    as    specified    by    n_skip_K\n\n                                                Returns    new    path    and    next    layer    index,    i.e.    K    +    n_skip_K,    in    a    tuple\n                                                "
        block_input = path
        skip_key = ('n_skip_%d' % K)
        n_skip = params.get(skip_key, 1)
        for i in range(n_skip):
            layer = (K + i)
            path = BatchNormalization()(path)
            path = Activation('relu')(path)
            filter_key = ('filter_width_%d' % layer)
            filter_width = params.get(filter_key, 3)
            path = convolutional.Convolution2D(nb_filter=params['filters_per_layer'], nb_row=filter_width, nb_col=filter_width, init='uniform', activation='linear', border_mode='same')(path)
        path = merge([block_input, path], mode='sum')
        return (path, (K + n_skip))
    layer = 1
    while (layer < params['layers']):
        (convolution_path, layer) = add_resnet_unit(convolution_path, layer, **params)
    if (layer > params['layers']):
        print 'Due    to    skipping,    ended    with    {}    layers    instead    of    {}'.format(layer, params['layers'])
    convolution_path = Activation('relu')(convolution_path)
    convolution_path = convolutional.Convolution2D(nb_filter=1, nb_row=1, nb_col=1, init='uniform', border_mode='same')(convolution_path)
    network_output = Flatten()(convolution_path)
    network_output = Bias()(network_output)
    network_output = Activation('softmax')(network_output)
    return Model(input=[model_input], output=[network_output])
