Python Tensorflow(GPU)vs.Numpy
我有两个使用梯度下降的线性回归的实现。一个在Tensorflow,一个在Numpy。我发现Numpy的速度比Tensorflow快3倍。这是我的密码- Tensorflow:Python Tensorflow(GPU)vs.Numpy,python,numpy,tensorflow,tensorflow-gpu,Python,Numpy,Tensorflow,Tensorflow Gpu,我有两个使用梯度下降的线性回归的实现。一个在Tensorflow,一个在Numpy。我发现Numpy的速度比Tensorflow快3倍。这是我的密码- Tensorflow: class network_cluster(object): def __init__(self, data_frame, feature_cols, label_cols): self.init_data(data_frame, feature_cols, label_cols)
class network_cluster(object):
def __init__(self, data_frame, feature_cols, label_cols):
self.init_data(data_frame, feature_cols, label_cols)
self.init_tensors()
def init_data(self, data_frame, feature_cols, label_cols):
self.data_frame = data_frame
self.feature_cols = feature_cols
self.label_cols = label_cols
def init_tensors(self):
self.features = tf.placeholder(tf.float32)
self.labels = tf.placeholder(tf.float32)
self.weights = tf.Variable(tf.random_normal((len(self.feature_cols), len(self.label_cols))))
self.const = tf.Variable(tf.random_normal((len(self.label_cols),)))
def linear_combiner(self):
return tf.add(tf.matmul(self.features, self.weights), self.const)
def predict(self):
return self.linear_combiner()
def error(self):
return tf.reduce_mean(tf.pow(self.labels - self.predict(), 2), axis = 0)
def learn_model(self, epocs = 100):
optimizer = tf.train.AdadeltaOptimizer(1).minimize(self.error())
error_rcd = []
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for epoc in range(epocs):
_, error = sess.run([optimizer, self.error()], feed_dict={
self.features: self.data_frame[self.feature_cols],
self.labels: self.data_frame[self.label_cols]
})
error_rcd.append(error[0])
return error_rcd
def get_coefs(self):
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
coefs = sess.run([self.weights, self.const])
return coefs
test_cluster = network_cluster(dataset, ['ship_jumps', 'npc_kills', 'ship_kills', 'pod_kills'], ['hour_of_week'])
%timeit test_cluster.learn_model(epocs = 100)
和numpy:
def grad_descent(dataset, features, predictor, max_iters = 10000):
def initialize_model(dataset, features, predictor):
constant_array = np.ones(shape = (len(dataset), 1))
features_array = dataset.loc[:, features].values
features_array = np.append(constant_array, features_array, axis = 1)
predict_array = dataset.loc[:, predictor].values
betas = np.zeros(shape = (len(features) + 1, len(predictor)))
return (features_array, predict_array, betas)
def calc_gradient(features_array, predict_array, betas):
prediction = np.dot(features_array, betas)
predict_error = predict_array - prediction
gradient = -2 * np.dot(features_array.transpose(), predict_error)
gradient_two = 2 * np.expand_dims(np.sum(features_array ** 2, axis = 0), axis = 1)
return (gradient, gradient_two)
def update_betas(gradient, gradient_two, betas):
new_betas = betas - ((gradient / gradient_two) / len(betas))
return new_betas
def model_error(features_array, predict_array, betas):
prediction = np.dot(features_array, betas)
predict_error = predict_array - prediction
model_error = np.sqrt(np.mean(predict_error ** 2))
return model_error
features_array, predict_array, betas = initialize_model(dataset, features, predictor)
prior_error = np.inf
for iter_count in range(max_iters):
gradient, gradient_two = calc_gradient(features_array, predict_array, betas)
betas = update_betas(gradient, gradient_two, betas)
curr_error = model_error(features_array, predict_array, betas)
if curr_error == prior_error:
break
prior_error = curr_error
return (betas, iter_count, curr_error)
%timeit grad_descent(dataset, ['ship_jumps', 'npc_kills', 'ship_kills', 'pod_kills'], ['hour_of_week'], max_iters = 100)
我正在使用Spyder IDE进行测试,我有一个Nvidia GPU(960)。Tensorflow代码的计时时间约为20秒,Numpy代码在同一数据集上的计时时间约为7秒。数据集几乎有100万行
我本以为Tensorflow会在这里轻松击败Numpy,但事实并非如此。假设我对使用Tensorflow还不熟悉,Numpy实现也不使用类,但使用Numpy还是比使用Tensorflow好3倍
希望能对我在这里犯的错误有一些想法/想法。无需详细查看您的代码(没有太多TF经验): 这个比较是有缺陷的
- Yaroslav的评论当然是正确的:GPU计算有一些开销(至少是数据准备;不确定这里记录的是哪种编译)
- 您在完整批处理模式下比较纯GD和ADADDelta,似乎:
- ADADDelta当然会带来一些开销(比计算梯度和乘以当前迭代次数还要多的操作),因为它是一种常见的方差减少方法,需要付出代价!
- 其想法是:投资一些额外的业务:
- 在给定一定学习率的情况下,删除所需的迭代次数
- (这要复杂得多:对大多数人来说->使用默认的学习速率实现良好的收敛)
- 其想法是:投资一些额外的业务:
- ADADDelta当然会带来一些开销(比计算梯度和乘以当前迭代次数还要多的操作),因为它是一种常见的方差减少方法,需要付出代价!
- 看起来你每个人只跑了100个纪元,并且记下了这个
- 那没有意义!
- 很有可能目标非常不同:
- 如果迭代大小不够
- 或者初始学习率选择不当
- 或者是相同的,但是不存在的提前停止确保了一个可能的更好的算法,并且证明了收敛性(根据一些标准)浪费了一些额外的时间进行所有迭代,直到达到100李>
- 很有可能目标非常不同:
- 那没有意义!
- (ADADDelta可能设计用于SGD设置,而不是GD)
对于数值优化的一般介绍,其中也谈到了很多关于一阶和二阶方法(中间有许多方法),我推荐可以在web上找到的方法。注意,当您执行“sess.run([optimizer,self.error()],feed_dict={”时,numpy和TensorFlow有单独的内存系统,它在每一步都将数据从numpy复制到TensorFlow GPU空间