Beispiel #1
0
    def __init__(self,
                 rnn_type,
                 ntoken,
                 ninp,
                 nhid,
                 nlayers,
                 dropout=0.5,
                 tie_weights=False):
        super(RNNModel, self).__init__()

        self.rnn_type = rnn_type
        self.nhid = nhid
        self.nlayers = nlayers
        self.initializer = Initializer()  #初始化,这个utils的实现?

        self.drop = nn.Dropout(dropout)  #两个参数,dropout 随机失活概率;inplace:默认是False

        self.encoder = nn.Embedding(
            ntoken, ninp
        )  #ninp是每一个embedding向量的维数  ntoken是size of the dictionary of embeddings
        self.initializer.init_embedding_(self.encoder)  #初始化embedding

        if rnn_type in ['LSTM', 'GRU']:
            self.rnn = getattr(nn, rnn_type)(
                ninp, nhid, nlayers, dropout=dropout,
                batch_first=True)  #getattr就是获得某属性的值,这里就是获取nn的网络类型值,如获得nn的LSTM
        else:
            try:
                nonlinearity = {
                    'RNN_TANH': 'tanh',
                    'RNN_RELU': 'relu'
                }[rnn_type]  #获取字典的这个rnn_type值
            except KeyError:
                raise ValueError(
                    """An invalid option for `--model` was supplied,
                                 options are ['LSTM', 'GRU', 'RNN_TANH' or 'RNN_RELU']"""
                )
            self.rnn = nn.RNN(ninp,
                              nhid,
                              nlayers,
                              nonlinearity=nonlinearity,
                              dropout=dropout,
                              batch_first=True)  #激活函数的选择

        self.decoder = nn.Linear(nhid, ntoken)
        # Optionally tie weights as in:
        # "Using the Output Embedding to Improve Language Models" (Press & Wolf 2016)
        # https://arxiv.org/abs/1608.05859
        # and
        # "Tying Word Vectors and Word Classifiers: A Loss Framework for Language Modeling" (Inan et al. 2016)
        # https://arxiv.org/abs/1611.01462
        if tie_weights:
            if nhid != ninp:
                raise ValueError(
                    'When using the tied flag, nhid must be equal to emsize'
                )  #若是softmax和word embedding 权重绑定。则hidden层和emsize相等
            self.decoder.weight = self.encoder.weight  #若绑定就是embedding的encoding.weight 和 decoder.weight相等
        else:
            self.initializer.init_linear_(self.decoder, nhid,
                                          dropout=dropout)  #对线性层进行初始化
Beispiel #2
0
    def stdp(self, wee, x, cutoff_weights):

        """ Apply STDP rule : Regulates synaptic strength between the pre(Xj) and post(Xi) synaptic neurons"""

        x = np.asarray(x)
        xt_1 = x[:, 0]
        xt = x[:, 1]
        wee_t = wee.copy()

        # STDP applies only on the neurons which are connected.

        for i in range(len(wee_t[0])):  # Each neuron i, Post-synaptic neuron

            for j in range(len(wee_t[0:])):  # Incoming connection from jth pre-synaptic neuron to ith neuron

                if wee_t[j][i] != 0.:  # Check connectivity

                    # Get the change in weight
                    delta_wee_t = self.eta_stdp * (xt[i] * xt_1[j] - xt_1[i] * xt[j])

                    # Update the weight between jth neuron to i ""Different from notation in article

                    wee_t[j][i] = wee[j][i] + delta_wee_t

        """ Prune the smallest weights induced by plasticity mechanisms; Apply lower cutoff weight"""
        wee_t = Initializer.prune_small_weights(wee_t, cutoff_weights[0])

        """Check and set all weights < upper cutoff weight """
        wee_t = Initializer.set_max_cutoff_weight(wee_t, cutoff_weights[1])

        return wee_t
Beispiel #3
0
    def istdp(self, wei, x, y, cutoff_weights):

        #  Apply iSTDP rule : Regulates synaptic strength between the pre(Yj) and post(Xi) synaptic neurons

        # Excitatory network activity
        x = np.asarray(x)  # Array sanity check
        xt_1 = x[:, 0]
        xt = x[:, 1]

        # Inhibitory network activity
        y = np.asarray(y)

        yt_1 = y[:, 0]
        yt = y[:, 1]

        # iSTDP applies only on the neurons which are connected.
        wei_t = wei.copy()

        for i in range(len(wei_t[0])):  # Each neuron i, Post-synaptic neuron: means for each column;

            for j in range(len(wei_t[0:])):  # Incoming connection from j, pre-synaptic neuron to ith neuron

                if wei_t[j][i] != 0.:  # Check connectivity

                    # Get the change in weight
                    delta_wei_t = - self.eta_inhib * yt_1[j] * (1 - xt[i] * (1 + 1 / self.mu_ip))

                    # Update the weight between jth neuron to i ""Different from notation in article

                    wei_t[j][i] = wei[j][i] + delta_wei_t

        """ Prune the smallest weights induced by plasticity mechanisms; Apply lower cutoff weight"""
        wei_t = Initializer.prune_small_weights(wei_t, cutoff_weights[0])

        """Check and set all weights < upper cutoff weight """
        wei_t = Initializer.set_max_cutoff_weight(wei_t, cutoff_weights[1])

        return wei_t
Beispiel #4
0
    def initialize_plasticity():

        """## NOTE: DO NOT TRANSPOSE THE WEIGHT MATRIX WEI FOR SORN 2 MODEL"""

        # Create and initialize sorn object and variables

        sorn_init = Sorn()
        WEE_init = sorn_init.initialize_weight_matrix(network_type='Sparse', synaptic_connection='EE',
                                                      self_connection='False',
                                                      lambd_w=20)
        WEI_init = sorn_init.initialize_weight_matrix(network_type='Sparse', synaptic_connection='EI',
                                                      self_connection='False',
                                                      lambd_w=40)
        WIE_init = sorn_init.initialize_weight_matrix(network_type='Dense', synaptic_connection='IE',
                                                      self_connection='False',
                                                      lambd_w=None)

        Wee_init = Initializer.zero_sum_incoming_check(WEE_init)
        # Wei_init = initializer.zero_sum_incoming_check(WEI_init.T)
        Wei_init = Initializer.zero_sum_incoming_check(WEI_init)
        Wie_init = Initializer.zero_sum_incoming_check(WIE_init)

        c = np.count_nonzero(Wee_init)
        v = np.count_nonzero(Wei_init)
        b = np.count_nonzero(Wie_init)

        print('Network Initialized')
        print('Number of connections in Wee %s , Wei %s, Wie %s' %(c, v, b))
        print('Shapes Wee %s Wei %s Wie %s' % (Wee_init.shape, Wei_init.shape, Wie_init.shape))

        # Normalize the incoming weights

        normalized_wee = Initializer.normalize_weight_matrix(Wee_init)
        normalized_wei = Initializer.normalize_weight_matrix(Wei_init)
        normalized_wie = Initializer.normalize_weight_matrix(Wie_init)

        te_init, ti_init = sorn_init.initialize_threshold_matrix(Sorn.te_min, Sorn.te_max, Sorn.ti_min, Sorn.ti_max)
        x_init, y_init = sorn_init.initialize_activity_vector(Sorn.ne, Sorn.ni)

        # Initializing variables from sorn_initialize.py

        wee = normalized_wee.copy()
        wei = normalized_wei.copy()
        wie = normalized_wie.copy()
        te = te_init.copy()
        ti = ti_init.copy()
        x = x_init.copy()
        y = y_init.copy()

        return wee, wei, wie, te, ti, x, y
Beispiel #5
0
    def structural_plasticity(wee):

        """ Add new connection value to the smallest weight between excitatory units randomly"""

        p_c = np.random.randint(0, 10, 1)

        if p_c == 0:  # p_c= 0.1

            """ Do structural plasticity """

            # Choose the smallest weights randomly from the weight matrix wee

            indexes = Initializer.get_unconnected_indexes(wee)

            # Choose any idx randomly
            idx_rand = random.choice(indexes)

            if idx_rand[0] == idx_rand[1]:
                idx_rand = random.choice(indexes)

            wee[idx_rand[0]][idx_rand[1]] = 0.001

        return wee
Beispiel #6
0
    def initialize_weight_matrix(network_type, synaptic_connection, self_connection, lambd_w):

        """
        Args:

        network_type(str) - Spare or Dense
        synaptic_connection(str) - EE,EI,IE: Note that Spare connection is defined only for EE connections
        self_connection(str) - True or False: i-->i ; Network is tested only using j-->i
        lambd_w(int) - Average number of incoming and outgoing connections per neuron

        Returns:
        weight_matrix(array) -  Array of connection strengths
        """

        if (network_type == "Sparse") and (self_connection == "False"):

            """ Generate weight matrix for E-E/ E-I connections with mean lamda incoming and 
               out-going connections per neuron """

            weight_matrix = Initializer.generate_lambd_connections(synaptic_connection, Sorn.ne, Sorn.ni, lambd_w, lambd_std=1)

        # Dense matrix for W_ie

        elif (network_type == 'Dense') and (self_connection == 'False'):

            # Gaussian distribution of weights
            # weight_matrix = np.random.randn(Sorn.ne, Sorn.ni) + 2 # Small random values from gaussian distribution
            # Centered around 1
            # weight_matrix.reshape(Sorn.ne, Sorn.ni)
            # weight_matrix *= 0.01 # Setting spectral radius

            # Uniform distribution of weights
            weight_matrix = np.random.uniform(0.0, 0.1, (Sorn.ne, Sorn.ni))
            weight_matrix.reshape((Sorn.ne, Sorn.ni))

        return weight_matrix
Beispiel #7
0
class RNNModel(nn.Module):
    """Container module with an encoder, a recurrent module, and a decoder."""
    def __init__(self,
                 rnn_type,
                 ntoken,
                 ninp,
                 nhid,
                 nlayers,
                 dropout=0.5,
                 tie_weights=False):
        super(RNNModel, self).__init__()

        self.rnn_type = rnn_type
        self.nhid = nhid
        self.nlayers = nlayers
        self.initializer = Initializer()  #初始化,这个utils的实现?

        self.drop = nn.Dropout(dropout)  #两个参数,dropout 随机失活概率;inplace:默认是False

        self.encoder = nn.Embedding(
            ntoken, ninp
        )  #ninp是每一个embedding向量的维数  ntoken是size of the dictionary of embeddings
        self.initializer.init_embedding_(self.encoder)  #初始化embedding

        if rnn_type in ['LSTM', 'GRU']:
            self.rnn = getattr(nn, rnn_type)(
                ninp, nhid, nlayers, dropout=dropout,
                batch_first=True)  #getattr就是获得某属性的值,这里就是获取nn的网络类型值,如获得nn的LSTM
        else:
            try:
                nonlinearity = {
                    'RNN_TANH': 'tanh',
                    'RNN_RELU': 'relu'
                }[rnn_type]  #获取字典的这个rnn_type值
            except KeyError:
                raise ValueError(
                    """An invalid option for `--model` was supplied,
                                 options are ['LSTM', 'GRU', 'RNN_TANH' or 'RNN_RELU']"""
                )
            self.rnn = nn.RNN(ninp,
                              nhid,
                              nlayers,
                              nonlinearity=nonlinearity,
                              dropout=dropout,
                              batch_first=True)  #激活函数的选择

        self.decoder = nn.Linear(nhid, ntoken)
        # Optionally tie weights as in:
        # "Using the Output Embedding to Improve Language Models" (Press & Wolf 2016)
        # https://arxiv.org/abs/1608.05859
        # and
        # "Tying Word Vectors and Word Classifiers: A Loss Framework for Language Modeling" (Inan et al. 2016)
        # https://arxiv.org/abs/1611.01462
        if tie_weights:
            if nhid != ninp:
                raise ValueError(
                    'When using the tied flag, nhid must be equal to emsize'
                )  #若是softmax和word embedding 权重绑定。则hidden层和emsize相等
            self.decoder.weight = self.encoder.weight  #若绑定就是embedding的encoding.weight 和 decoder.weight相等
        else:
            self.initializer.init_linear_(self.decoder, nhid,
                                          dropout=dropout)  #对线性层进行初始化

        # self.init_weights()

    def init_weights(self):
        initrange = 0.1
        self.encoder.weight.data.uniform_(-initrange, initrange)
        self.decoder.bias.data.zero_()
        self.decoder.weight.data.uniform_(-initrange, initrange)

    def forward(self, input, words_lengths):
        ''' Forward pass:
            - word embedding
            - 输入循环神经网络
            - 一个线性层从hidden state转化为输出单词表
        '''
        emb = self.drop(self.encoder(
            input))  # batch_size * seq_len * emb_dim   #将输入向量嵌入后随机置0
        emb = nn.utils.rnn.pack_padded_sequence(emb,
                                                words_lengths,
                                                batch_first=True)

        output_packed, _ = self.rnn(emb)  #通过网络得到输出
        output, _ = nn.utils.rnn.pad_packed_sequence(
            output_packed, batch_first=True
        )  # output: batch_size * seq_len * num_direct*hidden_dim,  num_direct = 1

        output = self.drop(output)  #对输出进行随机置0
        decoded = self.decoder(
            output.contiguous().view(
                output.size(0) * output.size(1), output.size(2))
        )  #decoder,output.contiguous()的一种可能解释是因为view要基于整块内存,而Tensor可能是零碎的,所以用contiguous变成连续
        return decoded.view(
            output.size(0), output.size(1),
            decoded.size(1))  # batch_size * seq_len * vocab_size
Beispiel #8
0
    def run_sorn(self, inp):
        # Initialize/Get the weight, threshold matrices and activity vectors
        matrix_collection = MatrixCollection(phase=self.phase, matrices=self.matrices)

        # Collect the network activity at all time steps

        X_all = [0] * self.time_steps
        Y_all = [0] * self.time_steps
        R_all = [0] * self.time_steps

        frac_pos_active_conn = []

        # To get the last activation status of Exc and Inh neurons

        for i in tqdm.tqdm(range(self.time_steps)):
            """ Generate white noise"""
            white_noise_e = Initializer.white_gaussian_noise(mu=0., sigma=0.04, t=Sorn.ne)
            white_noise_i = Initializer.white_gaussian_noise(mu=0., sigma=0.04, t=Sorn.ni)

            # Generate inputs
            # inp_ = np.expand_dims(Initializer.generate_normal_inp(10), 1)

            network_state = NetworkState(inp)  # Feed input and initialize network state

            # Buffers to get the resulting x and y vectors at the current time step and update the master matrix

            x_buffer, y_buffer = np.zeros((Sorn.ne, 2)), np.zeros((Sorn.ni, 2))

            # TODO: Return te,ti values in next version
            te_buffer, ti_buffer = np.zeros((Sorn.ne, 1)), np.zeros((Sorn.ni, 1))

            # Get the matrices and rename them for ease of reading

            Wee, Wei, Wie = matrix_collection.Wee, matrix_collection.Wei, matrix_collection.Wie
            Te, Ti = matrix_collection.Te, matrix_collection.Ti
            X, Y = matrix_collection.X, matrix_collection.Y

            """ Fraction of active connections between E-E network"""
            frac_pos_active_conn.append((Wee[i] > 0.0).sum())

            """ Recurrent drive"""

            r = network_state.recurrent_drive(Wee[i], Wei[i], Te[i], X[i], Y[i], white_noise_e)

            """Get excitatory states and inhibitory states given the weights and thresholds"""

            # x(t+1), y(t+1)
            excitatory_state_xt_buffer = network_state.excitatory_network_state(Wee[i], Wei[i], Te[i], X[i], Y[i],
                                                                                white_noise_e)

            inhibitory_state_yt_buffer = network_state.inhibitory_network_state(Wie[i], Ti[i], X[i], white_noise_i)

            """ Update X and Y """
            x_buffer[:, 0] = X[i][:, 1]  # xt -->(becomes) xt_1
            x_buffer[:, 1] = excitatory_state_xt_buffer.T  # New_activation; x_buffer --> xt

            y_buffer[:, 0] = Y[i][:, 1]
            y_buffer[:, 1] = inhibitory_state_yt_buffer.T

            """Plasticity phase"""

            plasticity = Plasticity()

            # TODO
            # Can be initialised outside loop--> Plasticity will receive dynamic args in future version

            # STDP
            Wee_t = plasticity.stdp(Wee[i], x_buffer, cutoff_weights=(0.0, 1.0))

            # Intrinsic plasticity
            Te_t = plasticity.ip(Te[i], x_buffer)

            # Structural plasticity
            Wee_t = plasticity.structural_plasticity(Wee_t)

            # iSTDP
            Wei_t = plasticity.istdp(Wei[i], x_buffer, y_buffer, cutoff_weights=(0.0, 1.0))

            # Synaptic scaling Wee
            Wee_t = Plasticity().ss(Wee_t)

            # Synaptic scaling Wei
            Wei_t = Plasticity().ss(Wei_t)

            """Assign the matrices to the matrix collections"""
            matrix_collection.weight_matrix(Wee_t, Wei_t, Wie[i], i)
            matrix_collection.threshold_matrix(Te_t, Ti[i], i)
            matrix_collection.network_activity_t(x_buffer, y_buffer, i)

            X_all[i] = x_buffer[:, 1]
            Y_all[i] = y_buffer[:, 1]
            R_all[i] = r

        plastic_matrices = {'Wee': matrix_collection.Wee[-1],
                            'Wei': matrix_collection.Wei[-1],
                            'Wie': matrix_collection.Wie[-1],
                            'Te': matrix_collection.Te[-1], 'Ti': matrix_collection.Ti[-1],
                            'X': X[-1], 'Y': Y[-1]}

        return plastic_matrices, X_all, Y_all, R_all, frac_pos_active_conn