code: def mutualInformation(sp, activeColumnsCurrentEpoch, column_1, column_2):
    
    i, j        = column_1, column_2
    batchSize   = activeColumnsCurrentEpoch.shape[0]
  
    # Activity Counts
    ci, cj, cij = 0., 0., dict([((0,0),0.), ((1,0),0.), ((0,1),0.), ((1,1),0.)])
    for t in range(batchSize):
      ai = activeColumnsCurrentEpoch[t, i]
      aj = activeColumnsCurrentEpoch[t, j]
      cij[(ai, aj)] += 1.
      ci += ai
      cj += aj
  
    # Mutual information calculation 
    Iij = 0
    for a,b in [(0,0), (1,0), (0,1), (1,1)]:
      # Compute probabilities
      pij = cij[(a,b)]/batchSize
      pi  = ci/batchSize if a == 1 else 1. - ci/batchSize
      pj  = cj/batchSize if b == 1 else 1. - cj/batchSize
      # Add current term of mutual information 
      Iij += pij * np.log2(pij/(pi*pj)) if pij > 0 else 0
  
    return Iij
docs: Computes the mutual information of the binary variables that represent 
    the activation probabilities of two columns. The mutual information I(X,Y) 
    of two random variables is given by
    \[
         I (X,Y)  = \sum_{x,y} p(x,y) log( p(x,y) / ( p(x) p(y) ) ).
    \]
    (https://en.wikipedia.org/wiki/Mutual_information)