Fortsetzung der vorherigen Sitzung.
Ich habe versucht, Amedas-Daten in Python zu importieren. Dieses Mal werde ich über das Thema des Versuchs einer Regressionsanalyse mit einem neuronalen Netzwerk schreiben.
Ich beschloss, die Beziehung zwischen Zeit und Windgeschwindigkeit eines Tages sehr einfach zu analysieren. Ist es in gewissem Sinne möglich, eine Funktion zu erstellen, die einer Tabelle mit einem neuronalen Netzwerk entspricht? Es ist wie damit zu experimentieren.
Ziehen Sie zunächst nur den Windgeschwindigkeits- und Zeitteil aus der zuletzt erstellten CSV-Datei. Es wird davon ausgegangen, dass die CSV-Datei nur Daten für einen Tag enthält.
import pandas as pd
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
# deta making???
csv_input = pd.read_csv(filepath_or_buffer="data_out.csv", encoding="ms932", sep=",")
#Anzahl der Eingabeelemente (Anzahl der Zeilen)*Die Anzahl der Spalten) wird zurückgegeben.
print(csv_input.size)
#Gibt das DataFrame-Objekt zurück, das nur für die angegebene Spalte extrahiert wurde.
x = np.array(csv_input[["hour"]])
y = np.array(csv_input[["wind"]])
#Normalisierung
x_max = np.max(x,axis=0)
x_min = np.min(x,axis=0)
y_max = np.max(y,axis=0)
y_min = np.min(y,axis=0)
x = (x - np.min(x,axis=0))/(np.max(x,axis=0) - np.min(x,axis=0))
y = (y - np.min(y,axis=0))/(np.max(y,axis=0) - np.min(y,axis=0))
Da es normalisiert ist, liegen sowohl x als auch y innerhalb von [0,1]. Lassen Sie uns überprüfen, wie es aussieht.
plt.plot(x,y,marker='x',label="true")
plt.legend()
Wenn Sie dies so überprüfen, sieht es wie folgt aus.
Es gibt 24 Punkte auf dem Grundstück, dh 24 Stunden. Es wird jeweils nur ein Punkt als Beispieldaten eingegeben. Mit anderen Worten, es handelt sich um Zeitreihen-Windgeschwindigkeitsdaten. Wenn Sie dies versuchen, schwankt es ziemlich.
Um es einfach auszudrücken: Wenn Sie sich dies als eine Tabelle mit 24 Stichproben vorstellen, können Sie die vertikale Achse y aus dem Wert auf der horizontalen Achse x vorhersagen. Lassen Sie uns dies als Beispiel eines neuronalen Netzwerks erstellen.
Nach der Untersuchung verschiedener Dinge scheint es, dass ein neuronales Netzwerk ... oder besser gesagt Deep Running eine Bibliothek namens Keras verwenden sollte. Ich war jedoch ein wenig süchtig nach der Installation, daher ist sie der Einfachheit halber am Tensorflow befestigt. tensorflow.layers Ich habe mich für so etwas entschieden. In diesem Fall scheint es verwendet werden zu können, solange der Tensorflow funktioniert.
Dieses Mal haben wir ein einfaches einschichtiges neuronales Netzwerk aufgebaut. Es gibt eine Eingabe, eine Ausgabe, und die Anzahl der Knoten in der mittleren Schicht ist angemessen.
In der Formel wird y wie folgt geschätzt.
y = \sum_{k=1}^{N} \left( h_k \phi( z_k ) \right)\\
= \sum_{k=1}^{N} \left( h_k \phi( w_{1k}x + w_{2k}) \right)
Die Vorspannungskomponente ist in der Figur jedoch weggelassen, und φ ist die Aktivierungsfunktion. Alles ist in Ordnung, aber lassen Sie uns einmal über die Sigmoid-Funktion nachdenken.
Das obige neuronale Netzwerkmodell schien wie folgt in Tensorflow-Schichten aufgebaut zu sein.
# make placeholder
x_ph = tf.placeholder(tf.float32, [None, 1])
y_ph = tf.placeholder(tf.float32, [None, 1])
# create newral parameter(depth=1,input:2 > output:1)
hidden1 = tf.layers.dense(x_ph, 24, activation=tf.nn.sigmoid)
newral_out = tf.layers.dense(hidden1, 1)
x_ph ist die Eingabe. newral_out ist der vorhergesagte Wert von y, der basierend auf x_ph berechnet wird. Y_ph, das hier nicht verwendet wird, wird für die Eingabe des richtigen Antwortwerts verwendet. hidden1 ist die z-Schicht (Zwischenschicht). Ich habe die Anzahl der Knoten auf 24 festgelegt, kann sie aber später ändern. Es ist ein wunderbares Wort, ein neuronales Netzwerk mit nur zwei Leitungen aufbauen zu können.
Wenn Sie dies bisher tun können, sollten Sie anscheinend die zu minimierenden Parameter definieren und eine Lernschleife erstellen. Bei der Wiederverwendung der zuvor verwendeten Probe lautet der Teil der Lernformel wie folgt.
# Minimize the mean squared errors.
loss = tf.reduce_mean(tf.square(newral_out - y_ph))
optimizer = tf.train.GradientDescentOptimizer(0.06)
train = optimizer.minimize(loss)
Der Loop-Teil ist ???
for k in range(10001):
if np.mod(k,1000) == 0:
# get Newral predict data
y_newral = sess.run( newral_out
,feed_dict = {
x_ph: x, #Ich habe die Eingabedaten in x gesetzt
y_ph: y.reshape(len(y),1) #Ich habe die richtigen Antwortdaten in t eingegeben
})
# errcheck??? ([newral predict] vs [true value])
err = y_newral - y
err = np.matmul(np.transpose(err),err)
# display err
print('[%d] err:%.5f' % (k,err))
# shuffle train_x and train_y
n = np.random.permutation(len(train_x))
train_x = train_x[n]
train_y = train_y[n].reshape([len(train_y), 1])
# execute train process
sess.run(train,feed_dict = {
x_ph: train_x, # x is input data
y_ph: train_y # y is true data
})
# check result infomation
y_newral = sess.run( newral_out
,feed_dict = {
x_ph: x, #Ich habe die Eingabedaten in x gesetzt
y_ph: y.reshape(len(y),1) #Ich habe die richtigen Antwortdaten in t eingegeben
})
# true info
plt.plot(x,y,marker='x',label="true")
# predict info
plt.plot(x,y_newral,marker='x',label="predict")
plt.legend()
Als Bonus ist auch ein Plot für die Endkontrolle enthalten. Jetzt hast du alles.
Lass es uns bewegen. Unterhalb der Konsolenausgabe.
[0] err:12.74091
[1000] err:1.21210
[2000] err:1.21163
[3000] err:1.21162
[4000] err:1.21162
[5000] err:1.21161
[6000] err:1.21161
[7000] err:1.21161
[8000] err:1.21160
[9000] err:1.21160
[10000] err:1.21159
Ich werde auch die Grafik einfügen.
Erster Eindruck ... Ernsthaft! !! !! !! (Enttäuscht) Es scheint nur eine lineare Annäherung zu sein. Wenn man die Bewegung betrachtet, nimmt der Fehler allmählich ab und konvergiert, so dass das Lernen selbst kein Problem zu sein scheint. Am Ende scheint es jedoch bei err = 1,2116 konvergiert zu haben. Damit macht es keinen Sinn, ein neuronales Netzwerk zu verwenden (lacht)
Ich denke, es ist eine schlechte Idee, die Ausgabe von z zu einer Sigmoid-Funktion zu machen, deshalb werde ich die Einstellung unten ein wenig ändern.
hidden1 = tf.layers.dense(x_ph, 24, activation=tf.nn.relu)
Was ist dann das Ergebnis?
[0] err:2.33927
[1000] err:1.18943
[2000] err:1.16664
[3000] err:1.13903
[4000] err:1.11184
[5000] err:1.09177
[6000] err:1.07951
[7000] err:1.06986
[8000] err:1.06280
[9000] err:1.05912
[10000] err:1.05760
Hmmm, es ist unterwegs kaputt gegangen (lacht) Ist es so etwas? ?? ?? Das mag in Ordnung sein, aber der erste Zweck war "eine Funktion anstelle einer Tabelle", also unterscheidet es sich ein wenig von dem, was ich tun möchte. Ich habe mir verschiedene Optionen in tensorflow.layers angesehen, aber ich wusste nicht, wie ich das machen soll, also habe ich einen etwas anderen Ansatz gewählt.
Was für eine Theorie ist das sogenannte neuronale Netzwerk? Es gab eine großartige Seite, um dies zu untersuchen.
■ Visueller Beweis, dass das neuronale Netzwerk beliebige Funktionen darstellen kann https://nnadl-ja.github.io/nnadl_site_ja/chap4.html
Es scheint, dass es sich um eine Übersetzung von Michael Nielsens Artikel handelt, aber ist es wirklich ein wunderbarer Inhalt, der die Essenz durchdringt, und kann ich ihn kostenlos sehen? Es geht darum. Weitere Informationen finden Sie im obigen Artikel, aber hier werde ich nur die wichtigen Schlussfolgerungen notieren.
Die erste, die Summe der Schrittfunktionen, wurde im Artikel kurz erwähnt. Ich war sehr froh, die nostalgischen Namen "Hahn Banachs Theorem" und "Reeses Ausdruckssatz" (ich habe Mathematik studiert) zu sehen. Diese Theoreme tauchten in der Funktionsanalyse auf (die Theorie, die Thematik in eine Reihe von Funktionen einzuteilen). Grob gesagt zeigte "Hahn-Banachs Theorem" Erweiterbarkeit, und "Reeses Ausdruckssatz" zeigte Existenz. Ich habe nur den Eindruck, dass "Reeses Ausdruckssatz" eine sehr schöne Theorie war (lacht). Zum Zeitpunkt der Schrittfunktion kam jedoch persönlich das Bild der Rubeg-Integration heraus, und ich interpretierte erweitert, dass es möglich wäre, eine sogenannte Rubeg-integrierbare Funktion auszudrücken. (Ich frage mich, ob die Rubeg-Integration auf der Existenz einer konvergenten Schrittfunktion basiert ~)
Bisher ist die Welt der Theorie, aber die zweite ist wichtig. Der Punkt war, dass die beiden Knoten in der mittleren Schicht als Einzelschrittfunktion fungieren konnten. Mit anderen Worten, wenn die Parameter gut bestimmt sind, kann ein neuronales Netzwerk als die Summe der Schrittfunktionen aufgebaut werden. Ich habe sofort eine Funktion erstellt, um die Parameter wie folgt zu bestimmen.
def calc_b_w(s,sign):
N = 1000 #Zwischenlagerung
# s = -b/w
if sign > 0:
b = -N
else:
b = N
if s != 0:
w = -b/s
else:
w = 1
return b,w
def calc_w_h(x,y):
#Sortiert in aufsteigender Reihenfolge von x, x in[0,1]Zu
K = len(x)
w_array = np.zeros([K*2,2])
h_array = np.zeros([K*2,1])
w_idx = 0
for k in range(K):
# x[k] , y[k]
if k > 0:
startX = x[k] + (x[k-1] - x[k])/2
else:
startX = 0
if k < K-1:
endX = x[k] + (x[k+1] - x[k])/2
else:
endX = 1
if k > 0:
b,w = calc_b_w(startX,1)
else:
b = 100
w = 1
# stepfunction 1stHalf
w_array[w_idx,0] = w
w_array[w_idx,1] = b
h_array[w_idx,0] = y[k]
w_idx += 1
# stepfunction 2ndHalf
b,w = calc_b_w(endX,1)
w_array[w_idx,0] = w
w_array[w_idx,1] = b
h_array[w_idx,0] = y[k]*-1
w_idx += 1
Eine Funktion namens calc_b_w bestimmt den Koeffizienten des Umwandlungsteils des neuronalen Netzwerks von der Eingangsschicht x zur Zwischenschicht z. Je größer N ist, desto näher ist die Schrittfunktion. Der Punkt, an dem sich s ändert. (0 <s <1) Vorzeichen ist eine Angabe, dass +1 oder 0 gesetzt ist, Erhöhen, wenn +1 und Ab, wenn 0. Ein Beispiel für s = 0,5 ist in der folgenden Abbildung dargestellt.
Mit anderen Worten, die Ausgabe von calc_b_w ist nur eine Seite (Seite vergrößern oder verkleinern) der Schrittfunktion, deren Größe +1 beträgt. Nur erhöhen, aber durch Kombinieren von zwei wird eine Schrittfunktion konstruiert. Wenn Sie den Änderungspunkt ein wenig verschieben und den mit umgekehrtem Ausgangscode hinzufügen, erhalten Sie eine impulsartige Wellenform. Bei dieser Rate bleibt die Ausgabegröße 1, multiplizieren Sie sie also mit dem Koeffizienten (h-Teil), um den Vorgang abzuschließen. Dann habe ich es basierend auf den in calc_w_h eingegebenen x und y möglich gemacht, diesen Parameter entsprechend zu berühren. Lassen Sie uns das Ergebnis überprüfen.
w_param,h_param = calc_w_h(x,y)
test_x = np.array(range(200))/200
test_y = np.zeros(len(test_x))
for k in range(len(test_x)):
test_y[k] = calc_New(test_x[k],h_param,w_param)
plt.plot(x,y,marker='x',label='input_info')
plt.plot(test_x,test_y,marker='x',label='predict')
plt.legend()
Es scheint, dass die Schrittfunktion erfolgreich konstruiert wurde. Zusätzlich ist die Funktion, die das neuronale Netzwerk unter Verwendung der eingestellten Parameter (w, h) berechnet, wie folgt definiert. (Super geeignet, tut mir leid)
def calc_New(x,h,w):
tmpx = np.array([x,1])
tmpx = tmpx.reshape(2,1)
longX = np.matmul(w,tmpx)
sigOUT = 1/(1+np.exp(-longX))
output = sigOUT * h
return np.sum( output )
Mit dem oben Gesagten wird ein neuronales Netzwerk wie eine Tabelle erstellt, die einer genauen Übereinstimmung nahe kommt. Lassen Sie es für alle Fälle als Programm ausführen, um die oben genannten Informationen zu erhalten. Ich denke es ist okay, aber ...
Sumimasen wird lange Zeit die Quelle einschließlich aller oben genannten Punkte schreiben.
import pandas as pd
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
def calc_b_w(s,sign):
N = 1000 #Zwischenlagerung
# s = -b/w
if sign > 0:
b = -N
else:
b = N
if s != 0:
w = -b/s
else:
w = 1
return b,w
def calc_w_h(x,y):
#Sortiert in aufsteigender Reihenfolge von x, x in[0,1]Zu
K = len(x)
w_array = np.zeros([K*2,2])
h_array = np.zeros([K*2,1])
w_idx = 0
for k in range(K):
# x[k] , y[k]
if k > 0:
startX = x[k] + (x[k-1] - x[k])/2
else:
startX = 0
if k < K-1:
endX = x[k] + (x[k+1] - x[k])/2
else:
endX = 1
if k > 0:
b,w = calc_b_w(startX,1)
else:
b = 100
w = 1
# stepfunction 1stHalf
w_array[w_idx,0] = w
w_array[w_idx,1] = b
h_array[w_idx,0] = y[k]
w_idx += 1
# stepfunction 2ndHalf
b,w = calc_b_w(endX,1)
w_array[w_idx,0] = w
w_array[w_idx,1] = b
h_array[w_idx,0] = y[k]*-1
w_idx += 1
return w_array,h_array
def calc_New(x,h,w):
tmpx = np.array([x,1])
tmpx = tmpx.reshape(2,1)
longX = np.matmul(w,tmpx)
sigOUT = 1/(1+np.exp(-longX))
output = sigOUT * h
return np.sum( output )
# deta making???
csv_input = pd.read_csv(filepath_or_buffer="data_out.csv", encoding="ms932", sep=",")
#Anzahl der Eingabeelemente (Anzahl der Zeilen)*Die Anzahl der Spalten wird zurückgegeben.
print(csv_input.size)
#Gibt das DataFrame-Objekt zurück, das nur für die angegebene Spalte extrahiert wurde.
x = np.array(csv_input[["hour"]])
y = np.array(csv_input[["wind"]])
# num of records
N = len(x)
#Normalisierung
x_max = np.max(x,axis=0)
x_min = np.min(x,axis=0)
y_max = np.max(y,axis=0)
y_min = np.min(y,axis=0)
x = (x - np.min(x,axis=0))/(np.max(x,axis=0) - np.min(x,axis=0))
y = (y - np.min(y,axis=0))/(np.max(y,axis=0) - np.min(y,axis=0))
train_x = x
train_y = y
w_init,h_init = calc_w_h(x,y)
test_x = np.array(range(200))/200
test_y = np.zeros(len(test_x))
for k in range(len(test_x)):
#print('k=%d' % k)
test_y[k] = calc_New(test_x[k],h_init,w_init)
x_ph = tf.placeholder(tf.float32, [None, 2])
y_ph = tf.placeholder(tf.float32, [None, 1])
W = tf.Variable(w_init,dtype=tf.float32)
h = tf.Variable(h_init,dtype=tf.float32)
# Before starting, initialize the variables. We will 'run' this first.
init = tf.global_variables_initializer()
# Launch the graph.
sess = tf.Session()
sess.run(init)
longX = tf.transpose(tf.matmul(W,tf.transpose(x_ph)))
sigOUT = tf.math.sigmoid(longX)
output = tf.matmul(sigOUT,h)
loss = tf.reduce_mean(tf.square(output - y_ph))
optimizer = tf.train.GradientDescentOptimizer(0.05)
train = optimizer.minimize(loss)
plt.plot(x,y,marker='x',label="true")
for k in range(201):
if np.mod(k,10) == 0:
#if 1:
# get Newral predict data
tmpX = np.hstack([x,np.ones(N).reshape([N,1])])
err = sess.run( loss
,feed_dict = {
x_ph: tmpX, #Ich habe die Eingabedaten in x gesetzt
y_ph: y.reshape(len(y),1) #Ich habe die richtigen Antwortdaten in t eingegeben
})
print('[%d] err:%.5f' % (k,err))
if np.mod(k,100) == 0 and k > 0:
tmpX = np.hstack([x,np.ones(N).reshape([N,1])])
newral_y = sess.run(output,feed_dict = {
x_ph: tmpX, # x is input data
y_ph: train_y # y is true data
})
plt.plot(x,newral_y,marker='x',label="k=%d" % k)
# shuffle train_x and train_y
n = np.random.permutation(len(train_x))
train_x = train_x[n]
train_y = train_y[n].reshape([len(train_y), 1])
tmpX = np.hstack([train_x,np.ones(N).reshape([N,1])])
# execute train process
sess.run(train,feed_dict = {
x_ph: tmpX, # x is input data
y_ph: train_y # y is true data
})
plt.legend()
Ergebnis ist ???
[0] err:0.00287
[10] err:0.00172
[20] err:0.00134
[30] err:0.00111
[40] err:0.00094
[50] err:0.00081
[60] err:0.00070
[70] err:0.00061
[80] err:0.00054
[90] err:0.00048
[100] err:0.00043
[110] err:0.00038
[120] err:0.00034
[130] err:0.00031
[140] err:0.00028
[150] err:0.00025
[160] err:0.00023
[170] err:0.00021
[180] err:0.00019
[190] err:0.00018
[200] err:0.00016
Es ist gegen fast Null konvergiert! Toll. Das Diagramm sieht auch wie folgt aus und ist optisch fast identisch.
(Irgendwie ist der Anfangswert des letzten Punktes fehlerhaft ...)
Sie haben die Tabellenfunktion erfolgreich implementiert. Es war ein Ansatz, der mit normalem maschinellem Lernen nicht möglich wäre, aber wenn Sie die Anfangswerte gut einstellen können, können Sie dies ohne Probleme tun. Dies ist jedoch wahrscheinlich ein Phänomen, das allgemein als Überlernen bezeichnet wird. Es ist nur zum Üben, also hoffe ich, dass Sie es sehen können.
Nächstes Mal werde ich etwas mehr über die Fortsetzung dieses Themas schreiben.
Recommended Posts