In Artikeln zu TensorFlow gab es nur wenige Anwendungsbeispiele außer neuronalen Netzen und Deep Learning. Daher habe ich als Beispiel die nicht-negative Matrixzerlegung (NMF) implementiert.
OS: Ubuntu 14.04 CPU: Core i7-3770 3.40GHz×8 Speicher: 16 GB TersorFlow: Ver.0.6.0 CPU-Modus Python version: 2.7
NMF ist ein Algorithmus, der die nicht negative Wertematrix V durch das Produkt zweier nicht negativer Wertmatrizen H und W approximiert. Es wird in einer Vielzahl von Bereichen wie Merkmalsextraktion, Dimensionsreduzierung, Bildverarbeitung als Clustering-Methode und natürlicher Sprache verwendet.
Eingabe: $ V \ in \ mathcal {R} ^ {m \ times n} _ {+}, \ r \ in \ mathcal {N} ^ + $
Ausgabe:$\underset{W,H} {\arg\min} ||V-WH||_{F}^{2}\ \ s.t.\ W \in \mathcal{R} _{+} ^{m \times r}, H \in \mathcal{R} _{+} ^ {r \times n} $
Dieses Mal verwenden wir die einfachste multiplikative Aktualisierungsregel, um NMF zu optimieren. Der MU-Algorithmus führt abwechselnd die folgenden Aktualisierungsausdrücke aus, bis sie konvergieren.
H_{a\mu} \leftarrow H_{a\mu}\frac{(W^TV)_{a\mu}}{(W^TWH)_{a\mu}},\ \
W_{ia} \leftarrow W_{ia}\frac{(VH^T)_{ia}}{(WHH^T)_{ia}}
Referenzlink: Algorithmen für die nicht negative Matrixfaktorisierung
Der Klassenkörper wird wie folgt implementiert.
tfnmf.py
# -*- coding: utf-8 -*-
from __future__ import division
import numpy as np
import tensorflow as tf
class TFNMF(object):
"""Non-negative Matrix Factorization by TensorFlow"""
def __init__(self, V, rank):
#Konvertieren Sie von der Numpy-Matrix in den Tensor von TensorFlow
V_ = tf.constant(V, dtype=tf.float32)
shape = V.shape
#Durchschnittliche sqrt(V.mean() / rank)Skalieren Sie auf eine einheitliche Zufallszahl
scale = 2 * np.sqrt(V.mean() / rank)
initializer = tf.random_uniform_initializer(maxval=scale)
#Matrix H.,W Variablengenerierung
self.H = H = tf.get_variable("H", [rank, shape[1]],
initializer=initializer)
self.W = W = tf.get_variable(name="W", shape=[shape[0], rank],
initializer=initializer)
#Speichern Sie W für die Konvergenzbeurteilung
W_old = tf.get_variable(name="W_old", shape=[shape[0], rank])
self._save_W = W_old.assign(W)
#MU-Algorithmus
#Update H.
Wt = tf.transpose(W)
WV = tf.matmul(Wt, V_)
WWH = tf.matmul(tf.matmul(Wt, W), H)
WV_WWH = WV / WWH
with tf.device('/cpu:0'):
#Wandelt ein Element, das nan enthält, um 0% in 0 um
WV_WWH = tf.select(tf.is_nan(WV_WWH),
tf.zeros_like(WV_WWH),
WV_WWH)
H_new = H * WV_WWH
self._update_H = H.assign(H_new)
#Update W.(H wurde aktualisiert)
Ht = tf.transpose(H)
VH = tf.matmul(V_, Ht)
WHH = tf.matmul(W, tf.matmul(H, Ht))
VH_WHH = VH / WHH
with tf.device('/cpu:0'):
#Wandelt ein Element, das nan enthält, um 0% in 0 um
WV_WWH = tf.select(tf.is_nan(WV_WWH),
tf.zeros_like(WV_WWH),
WV_WWH)
W_new = W * VH_WHH
self._update_W = W.assign(W_new)
#Gesamtänderung jedes Elements von W.
self._delta = tf.reduce_sum(tf.abs(W_old - W))
def run(self, sess, max_iter=200):
tf.initialize_all_variables().run()
for i in range(max_iter):
sess.run(self._save_W)
H, _ = sess.run([self.H, self._update_H])
W, _ = sess.run([self.W, self._update_W])
delta = sess.run(self._delta)
if delta < 0.001:
break
return W, H
Messen Sie die Ausführungszeit, indem Sie die Anzahl der von der CPU verwendeten Kerne ändern. Die Eingabe war eine 10000 x 10000-Zufallsmatrix, und die Anzahl der Ränge betrug 10.
Das Ausführungsskript lautet wie folgt.
main.py
# -*- coding: utf-8 -*-
from __future__ import print_function
import time
import numpy as np
import tensorflow as tf
from tfnmf import TFNMF
def main():
V = np.random.rand(10000,10000)
rank = 10
num_core = 8
tfnmf = TFNMF(V, rank)
config = tf.ConfigProto(inter_op_parallelism_threads=num_core,
intra_op_parallelism_threads=num_core)
with tf.Session(config=config) as sess:
start = time.time()
W, H = tfnmf.run(sess)
print("Computational Time: ", time.time() - start)
#Quadratische Fehlerberechnung
W = np.mat(W)
H = np.mat(H)
error = np.power(V - W * H, 2).sum()
print("Reconstruction Error: ", error)
if __name__ == '__main__':
main()
Dies ist das Ergebnis bei Ausführung mit 8 Kernen. Der Rekonstruktionsfehler repräsentiert den quadratischen Fehler, der die Zielfunktion ist.
$python main.py
I tensorflow/core/common_runtime/local_device.cc:40] Local device intra op parallelism threads: 8
I tensorflow/core/common_runtime/direct_session.cc:58] Direct session inter op parallelism threads: 8
Computational Time: 45.2025268078
Reconstruction Error: 8321195.31013
Es ist ein Diagramm der Ausführungszeit, wenn die Anzahl der Kerne von 1 auf 8 geändert wird.
Acht Kerne sind etwa 1,4-mal schneller als ein Kern. Der Overhead war größer als erwartet, und selbst wenn ich die Anzahl der Kerne erhöhte, erhöhte sich die Ausführungszeit nicht dramatisch. Es ist möglicherweise keine sehr effiziente Methode, jedes Mal, wenn W und H aktualisiert werden, sess.run () auszuführen.
Dieses Mal habe ich TensorFlow nur für die Matrixberechnung verwendet, daher fand ich, dass es nicht nützlich war, aber es ist wunderbar, die parallele Berechnung einfach beschreiben zu können. Nächstes Mal werde ich versuchen, eine Tensorzerlegung zu implementieren.
Recommended Posts