File size: 3,666 Bytes
0b8359d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================

"""Basic data management and plotting utilities."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os
import cPickle as pickle
import getpass
import numpy as np
import gc
import tensorflow as tf

#
# Python utlities
#
def exp_moving_average(x, alpha=0.9):
  res = []
  mu = 0
  alpha_factor = 1
  for x_i in x:
    mu += (1 - alpha)*(x_i - mu)
    alpha_factor *= alpha
    res.append(mu/(1 - alpha_factor))

  return np.array(res)

def sanitize(s):
  return s.replace('.', '_')

#
# Tensorflow utilities
#
def softplus(x):
  '''
  Let m = max(0, x), then,

  sofplus(x) = log(1 + e(x)) = log(e(0) + e(x)) = log(e(m)(e(-m) + e(x-m)))
             = m + log(e(-m) + e(x - m))

  The term inside of the log is guaranteed to be between 1 and 2.
  '''
  m = tf.maximum(tf.zeros_like(x), x)
  return m + tf.log(tf.exp(-m) + tf.exp(x - m))

def safe_log_prob(x, eps=1e-8):
  return tf.log(tf.clip_by_value(x, eps, 1.0))

def rms(x):
  return tf.sqrt(tf.reduce_mean(tf.square(x)))

def center(x):
  mu = (tf.reduce_sum(x) - x)/tf.to_float(tf.shape(x)[0] - 1)
  return x - mu

def vectorize(grads_and_vars, set_none_to_zero=False, skip_none=False):
  if set_none_to_zero:
    return tf.concat([tf.reshape(g, [-1]) if g is not None else
                         tf.reshape(tf.zeros_like(v), [-1]) for g, v in grads_and_vars], 0)
  elif skip_none:
    return tf.concat([tf.reshape(g, [-1]) for g, v in grads_and_vars if g is not None], 0)
  else:
    return tf.concat([tf.reshape(g, [-1]) for g, v in grads_and_vars], 0)

def add_grads_and_vars(a, b):
  '''Add grads_and_vars from two calls to tf.compute_gradients.'''
  res = []
  for (g_a, v_a), (g_b, v_b) in zip(a, b):
    assert v_a == v_b
    if g_a is None:
      res.append((g_b, v_b))
    elif g_b is None:
      res.append((g_a, v_a))
    else:
      res.append((g_a + g_b, v_a))
  return res

def binary_log_likelihood(y, log_y_hat):
  """Computes binary log likelihood.

  Args:
    y: observed data
    log_y_hat: parameters of the binary variables

  Returns:
    log_likelihood
  """
  return tf.reduce_sum(y*(-softplus(-log_y_hat)) +
                       (1 - y)*(-log_y_hat-softplus(-log_y_hat)),
                       1)

def cov(a, b):
  """Compute the sample covariance between two vectors."""
  mu_a = tf.reduce_mean(a)
  mu_b = tf.reduce_mean(b)
  n = tf.to_float(tf.shape(a)[0])

  return tf.reduce_sum((a - mu_a)*(b - mu_b))/(n - 1.0)

def corr(a, b):
  return cov(a, b)*tf.rsqrt(cov(a, a))*tf.rsqrt(cov(b, b))

def logSumExp(t, axis=0, keep_dims = False):
  '''Computes the log(sum(exp(t))) numerically stabily.

  Args:
    t: input tensor
    axis: which axis to sum over
    keep_dims: whether to keep the dim or not

  Returns:
    tensor with result

  '''
  m = tf.reduce_max(t, [axis])
  res = m + tf.log(tf.reduce_sum(tf.exp(t - tf.expand_dims(m, axis)), [axis]))

  if keep_dims:
    return tf.expand_dims(res, axis)
  else:
    return res