예제 #1
0
def inference(params):
    # Read data from file
    input_data = loadmat(params['input_file'])
    x = np.asarray(input_data['sample'], dtype=np.uint8)
    if 'theta' in input_data:
        theta_true = input_data['theta']
    else:
        theta_true = None
    params['N'], params['T'] = x.shape
    if not params['T'] % params['Delta'] == 0:
        print 'Error: T must be a multiple of Delta'
        sys.exit()
    params['M'] = params['T'] / params['Delta']
    theta_dim = (params['N'],params['N'],params['L'])
   
    # Generate S (calling it "windows" in code)
    print 'Generating window permutations'
    windows = []
    for k in range(params['M']):
        w = x[:,(k*params['Delta']):((k+1)*params['Delta'])]
        windows.append(window_permutations(w))
    n_w = map(len, windows)

    # Initialize theta
    theta_init = np.zeros(theta_dim)

    # Precompute statistics
    print 'Precomputing statistics'
    hits = [np.empty((n_w[0],)+theta_dim)]
    hits_observed = np.zeros(theta_dim)
    s_padded = np.zeros((params['N'],2*params['Delta']), dtype=np.bool)
    for w, s in enumerate(windows[0]):
        s_padded[:,params['Delta']:(2*params['Delta'])] = s
        for l in range(params['L']):
            tmin, tmax = params['Delta']-(l+1), 2*params['Delta']-(l+1)
            s_lagged = s_padded[:,tmin:tmax]
            hit = np.tensordot(s_lagged, s, axes = (1,1))
            hits[0][w,:,:,l] = hit
    hits_observed += hits[0][0]
    for k in range(1, params['M']):
        hits.append(np.empty((n_w[k-1],n_w[k])+theta_dim))
        for w_prev, s_prev in enumerate(windows[k-1]):
            s_padded[:,0:params['Delta']] = s_prev
            for w, s in enumerate(windows[k]):
                s_padded[:,params['Delta']:(2*params['Delta'])] = s
                for l in range(params['L']):
                    tmin, tmax = params['Delta']-(l+1), 2*params['Delta']-(l+1)
                    s_lagged = s_padded[:,tmin:tmax]
                    hit = np.tensordot(s_lagged, s, axes = (1,1))
                    hits[k][w_prev,w,:,:,l] = hit
        hits_observed += hits[k][0,0]

    # Common DP code used for likelihood and gradient calculations
    def dp(theta):
        h = [None] * params['M']
        h[0] = np.empty(n_w[0])
        for w in range(n_w[0]):
            h[0][w] = np.sum(theta * hits[0][w])
        for k in range(1, params['M']):
            h[k] = np.empty((n_w[k-1], n_w[k]))
            for w_prev in range(n_w[k-1]):
                for w in range(n_w[k]):
                    h[k][w_prev,w] = np.sum(theta * hits[k][w_prev,w])

        b = [None] * (params['M']+1)
        b[params['M']] = np.zeros(n_w[params['M']-1])
        for k in range(params['M']-1, 0, -1):
            b[k] = np.empty(n_w[k-1])
            for w_prev in range(n_w[k-1]):
                b[k][w_prev] = logaddexp(h[k][w_prev] + b[k+1])

        return h, b

    # Define objective function, in this case, the negative log-likelihood
    def neg_log_likelihood(theta_vec):
        theta = np.reshape(theta_vec, theta_dim)

        h, b = dp(theta)
        
        log_kappa = logaddexp(h[0] + b[1])

        nll = log_kappa
        nll -= h[0][0]
        for k in range(1, params['M']):
            nll -= h[k][0,0]
        return nll
    
    # Define gradient of the objective function
    def grad_neg_log_likelihood(theta_vec):
        theta = np.reshape(theta_vec, theta_dim)

        h, b = dp(theta)

        # Compute expected statistics
        w_prob = unlog(h[0] + b[1])
        hits_expected = fast_average(hits[0], w_prob)
        for k in range(1, params['M']):
            w_prob_new = np.zeros(n_w[k])
            for w_prev in range(n_w[k-1]):
                w_weight = unlog(h[k][w_prev,:] + b[k+1])
                w_prob_new += w_weight * w_prob[w_prev]
                hits_expected += (w_prob[w_prev] *
                                  fast_average(hits[k][w_prev], w_weight))
            w_prob = w_prob_new

        return np.reshape(hits_expected - hits_observed, theta_vec.shape)

    # Callback for displaying state during optimization
    def show_theta(theta_vec):
        theta = np.reshape(theta_vec, (params['N'], params['N'], params['L']))
        if theta_true is None:
            print theta
        else:
            diff = np.reshape(theta - theta_true, theta_vec.shape)
            print np.sqrt(np.dot(diff, diff))

    # Do optimization
    print 'Starting optimization'
    theta_opt = opt.fmin_bfgs(f = neg_log_likelihood,
                              fprime = grad_neg_log_likelihood,
                              x0 = theta_init,
                              callback = show_theta)

    # Output
    print 'x'
    print x
    print

    print 'Parameters'
    for param in params:
        print '%s: %s' % (param, str(params[param]))
    print

    print 'Inferred theta'
    print np.reshape(theta_opt, (params['N'], params['N'], params['L']))
예제 #2
0
    if method_name == 'random_periodic':
        periods = params['M'] * np.random.normal(1, 1, params['N'])
        phases = np.random.uniform(0.0, 2.0*np.pi, params['N'])
    for k in range(params['M']):
        window = []
        if method_name == 'random_uniform':
            p = np.random.uniform(method_params['p_min'],method_params['p_max'])
            w_raw = np.random.binomial(1, p, (params['N'],params['Delta']))
        if method_name == 'random_periodic':
            w_raw = np.empty((params['N'], params['Delta']))
            for i in range(params['N']):
                p = (method_params['baseline'] +
                     method_params['scale'] * np.sin(periods[i]*k + phases[i]))
                w_raw[i,:] = np.random.binomial(1, p, (1, params['Delta']))
        w = np.array(w_raw, dtype='uint8')
        windows.append(window_permutations(w))
n_w = map(len, windows)

# Tabulate log-potential functions: h_1, h_2, ..., h_M
print 'Tabulating log-potential functions'
h = [np.empty(n_w[0])]
s_padded = np.zeros((params['N'],2*params['Delta']), dtype='uint8')
hits = np.zeros((params['N'],params['N'],params['L']), dtype='int32')
for w, s in enumerate(windows[0]):
    s_padded[:,params['Delta']:(2*params['Delta'])] = s
    hits[:,:,:] = 0
    for l in range(params['L']):
        tmin, tmax = params['Delta'] - (l+1), 2*params['Delta'] - (l+1)
        s_lagged = s_padded[:,tmin:tmax]
        hits[:,:,l] = np.tensordot(s_lagged, s, axes = (1,1))
    h[0][w] = np.sum(theta * hits)