La dernière fois, j'ai écrit comment utiliser le modèle d'analyse de régression dans Keras. Cette fois, j'écrirai un peu sur le modèle de classification.
Tout d'abord, il existe diverses informations sur la façon de créer un modèle de classification dans Keras, mais je me suis référé au blog suivant.
Exemple d'apprentissage en profondeur extrêmement simple par Keras
Je me réfère également au site officiel de Keras.
Les informations utilisées sont les mêmes que la dernière fois, les données d'un jour d'Amedas. Il est à nouveau montré ci-dessous. (J'ai l'impression que la façon de le faire était écrite autour de celle-là)
data_out.csv
year,month,day,hour,temp,wind,angle,weather,
2019,8,13,1,24.9,1.4,0,2
2019,8,13,2,24.1,2.2,0,2
2019,8,13,3,23.8,1.4,0,2
2019,8,13,4,23.5,1.2,0,2
2019,8,13,5,23.2,1.8,0,2
2019,8,13,6,23.9,0.7,15,2
2019,8,13,7,25.1,0.9,13,2
2019,8,13,8,26.7,1.0,10,2
2019,8,13,9,28.6,1.6,5,2
2019,8,13,10,30.3,1.2,8,2
2019,8,13,11,30.6,1.3,11,2
2019,8,13,12,31.4,2.5,1,2
2019,8,13,13,33.3,2.0,5,2
2019,8,13,14,33.0,2.3,16,2
2019,8,13,15,33.9,1.8,3,2
2019,8,13,16,32.2,3.2,13,2
2019,8,13,17,29.4,1.0,15,10
2019,8,13,18,27.1,4.4,11,10
2019,8,13,19,25.9,3.7,13,10
2019,8,13,20,26.0,2.4,16,4
2019,8,13,21,26.0,0.9,16,4
2019,8,13,22,25.6,1.3,16,2
2019,8,13,23,25.4,2.6,0,2
Je me demandais quoi classer, mais si la vitesse du vent est supérieure à une certaine valeur (par exemple, ** 2m **), je la diviserai en deux modèles: vent fort, et sinon, brise / pas de vent.
La préparation des données (ingestion, normalisation, etc.) est la suivante.
import pandas as pd
import numpy as np
# deta making???
csv_input = pd.read_csv(filepath_or_buffer="data_out.csv",
encoding="ms932",
sep=",")
#Nombre d'éléments d'entrée (nombre de lignes)*Le nombre de colonnes) sera renvoyé.
#Renvoie l'objet DataFrame extrait uniquement pour la colonne spécifiée.
x = np.array(csv_input[["hour"]])
y = np.array(csv_input[["wind"]])
# num of records
N = len(x)
#Normalisation
x_max = np.max(x,axis=0)
x_min = np.min(x,axis=0)
x = (x - np.min(x,axis=0))/(np.max(x,axis=0) - np.min(x,axis=0))
# y > 2[m] : strong
# y <= 2[m] : weak
y_new = np.zeros(len(y),dtype=int)
for k in range(len(y)):
if y[k] > 2:
y_new[k] = 1
y = y_new.reshape(y.shape)
y contient les données de sortie
――Quand 1 → Jugé comme un vent fort --Quand 0 → Jugé comme brise / pas de vent
Il est devenu. Pour apprendre cela, créons un modèle dans Keras avec le code suivant.
#Créer un modèle d'apprentissage
model = Sequential()
#Couche entièrement connectée(1 couche->30 couches)
model.add(Dense(input_dim=1, output_dim=30, bias=True))
#Fonction d'activation(Fonction sigmoïde)
model.add(Activation("sigmoid"))
#Couche entièrement connectée(30 couches->1 couche)
model.add(Dense(output_dim=1))
#Fonction d'activation(Fonction sigmoïde)
model.add(Activation("sigmoid"))
#Compilez le modèle
model.compile(loss="binary_crossentropy", optimizer="sgd", metrics=["accuracy"])
#Effectuer l'apprentissage
model.fit(x, y, epochs=5000, batch_size=32, verbose=1)
Lorsqu'il n'y a qu'une seule partie de sortie finale, la sélection de binary_crossentropy semble être la bonne réponse. Les éléments suivants sont considérés comme les fonctions d'erreur. (Équation simplifiée 5.23 à la page 236 pour la reconnaissance de formes et l'apprentissage automatique)
E(\textbf{w}) = - \sum_{n=1}^{N}
\{ t_{n} \ln y (x_n,\textbf{w}) + (1-t_{n})\ln (1-y (x_n,\textbf{w})) \}
L'indice n indique le nombre d'échantillons et t_n est la valeur correcte (1 ou 0) correspondant à x_n. y (x_n, w) signifie la sortie d'inférence lorsque l'entrée = x_n et le paramètre de réseau neuronal = w (à ce moment, E (w) = 0 et la valeur minimale est prise). Le processus d'apprentissage consiste à trouver w tel que t_n = y (x_n, w) soit valable pour tout x_n.
Ici, pour l'évaluation des résultats, préparez une fonction qui donne le taux de réponse correct qui a été donné auparavant. (Bien qu'il apparaisse dans le journal Keras, je l'ai préparé moi-même pour la pratique)
# y:predict
# t:true
def checkOKPercent(y,t):
# from predict param
sign_newral = np.sign(np.array(y).reshape([len(t),1]) - 0.5)
# from true param
sign_orig = np.sign(np.array(t.reshape([len(t),1])) - 0.5)
# are there same sign??
NGCNT = np.sum(np.abs(sign_newral-sign_orig))/2
# calc NG percent in [0.0-1.0]
NGPer = NGCNT / len(t)
# return OK percent [0.0-1.0]
return 1.0-NGPer
La sortie du réseau neuronal, y (x_n, w), prend en fait une valeur arbitraire (float ???) entre [0,1]. Si elle est égale ou supérieure à 0,5, c'est un vent fort, et si elle est inférieure à 0,5, c'est un jeu d'enfant / Cela signifie pas de vent.
Résumez ce qui précède et collez la source ci-dessous.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers import Activation, Dense
# y:predict
# t:true
def checkOKPercent(y,t):
# from predict param
sign_newral = np.sign(np.array(y).reshape([len(t),1]) - 0.5)
# from true param
sign_orig = np.sign(np.array(t.reshape([len(t),1])) - 0.5)
# are there same sign??
NGCNT = np.sum(np.abs(sign_newral-sign_orig))/2
# calc NG percent in [0.0-1.0]
NGPer = NGCNT / len(t)
# return OK percent [0.0-1.0]
return 1.0-NGPer
# deta making???
csv_input = pd.read_csv(filepath_or_buffer="data_out.csv",
encoding="ms932",
sep=",")
#Nombre d'éléments d'entrée (nombre de lignes)*Le nombre de colonnes) sera renvoyé.
#Renvoie l'objet DataFrame extrait uniquement pour la colonne spécifiée.
x = np.array(csv_input[["hour"]])
y = np.array(csv_input[["wind"]])
# num of records
N = len(x)
#Normalisation
x_max = np.max(x,axis=0)
x_min = np.min(x,axis=0)
x = (x - np.min(x,axis=0))/(np.max(x,axis=0) - np.min(x,axis=0))
# y > 2[m] : strong
# y <= 2[m] : weak
y_new = np.zeros(len(y),dtype=int)
for k in range(len(y)):
if y[k] > 2:
y_new[k] = 1
y = y_new.reshape(y.shape)
#Créer un modèle d'apprentissage
model = Sequential()
#Couche entièrement connectée(1 couche->30 couches)
model.add(Dense(input_dim=1, output_dim=30, bias=True))
#Fonction d'activation(Fonction sigmoïde)
model.add(Activation("sigmoid"))
#Couche entièrement connectée(30 couches->1 couche)
model.add(Dense(output_dim=1))
#Fonction d'activation(Fonction sigmoïde)
model.add(Activation("sigmoid"))
#Compilez le modèle
model.compile(loss="binary_crossentropy", optimizer="sgd", metrics=["accuracy"])
#Effectuer l'apprentissage
model.fit(x, y, epochs=5000, batch_size=32, verbose=1)
#Tracé de la valeur réelle
plt.plot(x,y,marker='x',label="true")
#Calculer les résultats Keras avec inférence,afficher
y_predict = model.predict(x)
#Graphique des résultats du calcul Keras
plt.plot(x,y_predict,marker='x',label="predict")
#Affichage de la légende
plt.legend()
# display result
print('OK %.2f[percent]' % (checkOKPercent(y_predict,y)*100.0))
Si vous remarquez, vous pouvez supprimer tensorflow de l'importation ... Maintenant, quand je trace le résultat, il ressemble à ce qui suit.
L'axe horizontal est le temps (normalisé) et l'axe vertical indique si le vent est fort ou non. Le bleu est la bonne réponse, et l'orange est le résultat du réseau neuronal. D'une certaine manière ... Après tout, cela ressemble à une approximation en ligne droite.
Le degré de convergence est affiché sur la console, donc vérifions-le.
Epoch 4994/5000
23/23 [==============================] - 0s 87us/step - loss: 0.6013 - acc: 0.6522
Epoch 4995/5000
23/23 [==============================] - 0s 87us/step - loss: 0.6012 - acc: 0.6522
Epoch 4996/5000
23/23 [==============================] - 0s 43us/step - loss: 0.6012 - acc: 0.6522
Epoch 4997/5000
23/23 [==============================] - 0s 43us/step - loss: 0.6012 - acc: 0.6522
Epoch 4998/5000
23/23 [==============================] - 0s 43us/step - loss: 0.6012 - acc: 0.6522
Epoch 4999/5000
23/23 [==============================] - 0s 43us/step - loss: 0.6012 - acc: 0.6522
Epoch 5000/5000
23/23 [==============================] - 0s 43us/step - loss: 0.6012 - acc: 0.6522
OK 65.22[percent]
Comme la perte converge vers 0,6012, cela semble fonctionner comme une logique. Cependant, le taux de réponse correcte est de 65,22%. Même si je le prédis d'un côté ou de l'autre, je sens que ça ira comme ça, donc les performances ne sont pas bonnes.
J'ai donc essayé le modèle qui définit la valeur initiale du réseau neuronal comme je l'ai fait la dernière fois. Du coup je posterai tout le code source.
import pandas as pd
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers import Activation, Dense
from keras.utils.np_utils import to_categorical
from keras import backend as K
import keras
# y:predict
# t:true
def checkOKPercent(y,t):
# from predict param
sign_newral = np.sign(np.array(y).reshape([len(t),1]) - 0.5)
# from true param
sign_orig = np.sign(np.array(t.reshape([len(t),1])) - 0.5)
# are there same sign??
NGCNT = np.sum(np.abs(sign_newral-sign_orig))/2
# calc NG percent in [0.0-1.0]
NGPer = NGCNT / len(t)
# return OK percent [0.0-1.0]
return 1.0-NGPer
# init infomation for keras layers or models
class InitInfo:
# constractor
# x:input y:output
def __init__(self,x,y):
self.x = x
self.y = y
# calc coefficient of keras models(1st layer)
# input s:changing point in [0,1]
# sign:[1]raise,[0]down
# return b:coefficient of bias
# w:coefficient of x
# notice - it can make like step function using this return values(s,sign)
def calc_b_w(self,s,sign):
N = 1000 #Stockage temporaire
# s = -b/w
if sign > 0:
b = -N
else:
b = N
if s != 0:
w = -b/s
else:
w = 1
return b,w
# calc coefficient of keras models(1st and 2nd layer)
def calc_w_h(self):
K = len(self.x)
# coefficient of 1st layer(x,w)
w_array = np.zeros([K*2,2])
# coefficient of 2nd layer
h_array = np.zeros([K*2,1])
w_idx = 0
for k in range(K):
# x[k] , y[k]
# make one step function
# startX : calc raise point in [0,1]
if k > 0:
startX = self.x[k] + (self.x[k-1] - self.x[k])/2
else:
startX = 0
# endX : calc down point in [0,1]
if k < K-1:
endX = self.x[k] + (self.x[k+1] - self.x[k])/2
else:
endX = 1
# calc b,w
if k > 0:
b,w = self.calc_b_w(startX,1)
else:
# init???
b = 100
w = 1
# stepfunction 1stHalf
# __________
# 0 ________|
#
w_array[w_idx,0] = w
w_array[w_idx,1] = b
h_array[w_idx,0] = self.y[k]
w_idx += 1
# stepfunction 2ndHalf
#
# 0 __________
# |________
b,w = self.calc_b_w(endX,1)
w_array[w_idx,0] = w
w_array[w_idx,1] = b
h_array[w_idx,0] = self.y[k]*-1
# shape of 1st + 2nd is under wave
# _
# 0 ________| |________
#
w_idx += 1
# record param
self.w = w_array
self.h = h_array
self.w_init = w_array[:,0]
self.b_init = w_array[:,1]
self.paramN = len(h_array)
return
# for bias coefficients setting
def initB(self, shape, name=None):
value = self.b_init
value = value.reshape(shape)
return K.variable(value, name=name)
# for w coefficients (x) setting
def initW(self, shape, name=None):
value = self.w_init
value = value.reshape(shape)
return K.variable(value, name=name)
# for h coefficients setting
def initH(self, shape, name=None):
value = self.h
value = value.reshape(shape)
return K.variable(value, name=name)
# deta making???
csv_input = pd.read_csv(filepath_or_buffer="data_out.csv",
encoding="ms932",
sep=",")
#Nombre d'éléments d'entrée (nombre de lignes)*Le nombre de colonnes) sera renvoyé.
print(csv_input.size)
#Renvoie l'objet DataFrame extrait uniquement pour la colonne spécifiée.
x = np.array(csv_input[["hour"]])
y = np.array(csv_input[["wind"]])
print(y.shape)
# num of records
N = len(x)
#Normalisation
x_max = np.max(x,axis=0)
x_min = np.min(x,axis=0)
x = (x - np.min(x,axis=0))/(np.max(x,axis=0) - np.min(x,axis=0))
# y > 2[m] : strong
# y <= 2[m] : weak
y_new = np.zeros(len(y),dtype=int)
for k in range(len(y)):
if y[k] > 2:
y_new[k] = 1
y_new = y_new.reshape(y.shape)
y = np.array(y_new,dtype=float)
# create InitInfo object
objInitInfo = InitInfo(x,y_orig)
# calc init value of w and h(and bias)
objInitInfo.calc_w_h()
#Créer un modèle d'apprentissage
model = Sequential()
#Couche entièrement connectée(1 couche->Couche XXX)
model.add(Dense(input_dim=1, output_dim=objInitInfo.paramN,
bias=True,
kernel_initializer=objInitInfo.initW,
bias_initializer=objInitInfo.initB))
#Fonction d'activation(Fonction sigmoïde)
model.add(Activation("sigmoid"))
#Couche entièrement connectée(Couche XXX->2 couches)
model.add(Dense(output_dim=1,kernel_initializer=objInitInfo.initH))
#Fonction d'activation(fonction softmax)
model.add(Activation("sigmoid"))
sgd_ = keras.optimizers.SGD(lr=0.05)
cb = keras.callbacks.EarlyStopping(monitor='loss',
min_delta=0.0004,
patience=1,
verbose=0,
mode='auto',
baseline=None)
#Compilez le modèle
model.compile(loss="binary_crossentropy", optimizer=sgd_, metrics=["accuracy"])
#Effectuer l'apprentissage
model.fit(x, y, epochs=5000, batch_size=32, verbose=1,callbacks=[cb])
#Tracé de la valeur réelle
plt.plot(x,y,marker='x',label="true")
#Calculer les résultats Keras avec inférence,afficher
y_predict = model.predict(x)
#Graphique des résultats du calcul Keras
plt.plot(x,y_predict,marker='x',label="predict")
#Affichage de la légende
plt.legend()
# display result
print('OK per %.2f ' % (checkOKPercent(y_predict,y)*100.0))
Nous avons également ajouté un paramètre de rappel qui vous permet de quitter lorsqu'il est déterminé qu'il a convergé. Le résultat est ???
23/23 [==============================] - 0s 0us/step - loss: 0.2310 - acc: 1.0000
NG per 100.00
Génial, le taux de réponse correcte est maintenant de 100%! !! !! Il s'est avéré que même la valeur initiale devait être bien définie. Cependant, il semble que ce n'est pas polyvalent? ?? ??
J'ai essayé de laisser tomber le coefficient au hasard, et cela semblait fonctionner avec les paramètres suivants.
# for bias coefficients setting
def initB(shape, name=None):
L = np.prod(shape)
value = np.ones(L).reshape(shape)*(-1000)
return K.variable(value, name=name)
# for w coefficients (x) setting
def initW(shape, name=None):
value = 1000/(np.random.random(shape))
return K.variable(value, name=name)
C'est un coefficient à mettre de x à la couche intermédiaire, mais le côté Bias est fixé à 1000, le côté x (w) fait un nombre aléatoire de [0,1], et l'assigne de manière appropriée à 1000 / nombre aléatoire (plus de 1000) ( Je suis désolé si je me réveille à zéro pour cent).
import pandas as pd
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers import Activation, Dense
from keras.utils.np_utils import to_categorical
from keras import backend as K
import keras
# y:predict
# t:true
def checkOKPercent(y,t):
# from predict param
sign_newral = np.sign(np.array(y).reshape([len(t),1]) - 0.5)
# from true param
sign_orig = np.sign(np.array(t.reshape([len(t),1])) - 0.5)
# are there same sign??
NGCNT = np.sum(np.abs(sign_newral-sign_orig))/2
# calc NG percent in [0.0-1.0]
NGPer = NGCNT / len(t)
# return OK percent [0.0-1.0]
return 1.0-NGPer
# for bias coefficients setting
def initB(shape, name=None):
L = np.prod(shape)
value = np.ones(L).reshape(shape)*(-1000)
return K.variable(value, name=name)
# for w coefficients (x) setting
def initW(shape, name=None):
value = 1000/(np.random.random(shape))
return K.variable(value, name=name)
# deta making???
csv_input = pd.read_csv(filepath_or_buffer="data_out.csv",
encoding="ms932",
sep=",")
#Renvoie l'objet DataFrame extrait uniquement pour la colonne spécifiée.
x = np.array(csv_input[["hour"]])
y = np.array(csv_input[["wind"]])
# num of records
N = len(x)
#Normalisation
x_max = np.max(x,axis=0)
x_min = np.min(x,axis=0)
x = (x - np.min(x,axis=0))/(np.max(x,axis=0) - np.min(x,axis=0))
# y > 2[m] : strong
# y <= 2[m] : weak
y_new = np.zeros(len(y),dtype=int)
for k in range(len(y)):
if y[k] > 2:
y_new[k] = 1
y_new = y_new.reshape(y.shape)
y = np.array(y_new,dtype=float)
#Créer un modèle d'apprentissage
model = Sequential()
#Couche entièrement connectée(1 couche->Couche XXX)
model.add(Dense(input_dim=1, output_dim=50,
bias=True,
kernel_initializer=initW,
bias_initializer=initB))
#Fonction d'activation(Fonction sigmoïde)
model.add(Activation("sigmoid"))
#Couche entièrement connectée(Couche XXX->2 couches)
model.add(Dense(output_dim=1))
#Fonction d'activation(fonction softmax)
model.add(Activation("sigmoid"))
sgd_ = keras.optimizers.SGD(lr=0.3)
cb = keras.callbacks.EarlyStopping(monitor='loss',
min_delta=0.0001,
patience=1,
verbose=0,
mode='auto',
baseline=None)
#Compilez le modèle
model.compile(loss="binary_crossentropy", optimizer=sgd_, metrics=["accuracy"])
#Effectuer l'apprentissage
model.fit(x, y, epochs=5000, batch_size=32, verbose=1,callbacks=[cb])
#Tracé de la valeur réelle
plt.plot(x,y,marker='x',label="true")
#Calculer les résultats Keras avec inférence,afficher
y_predict = model.predict(x)
#Graphique des résultats du calcul Keras
plt.plot(x,y_predict,marker='x',label="predict")
#Affichage de la légende
plt.legend()
# display result
print('OK per %.2f ' % (checkOKPercent(y_predict,y)*100.0))
Le résultat était également bon.
Epoch 1032/5000
23/23 [==============================] - 0s 87us/step - loss: 0.1018 - acc: 1.0000
NG per 100.00
Le nombre de nœuds dans la couche intermédiaire a été fixé à 50, mais dans de nombreux cas, le taux de réponse correcte n'a pas atteint 100%. Il semble que la stabilité augmentera en augmentant le nombre de nœuds (selon les résultats expérimentaux).
■ Lorsque le nombre de nœuds est de 150
Epoch 5000/5000
23/23 [==============================] - 0s 0us/step - loss: 0.0058 - acc: 1.0000
OK per 100.00
Cette fois, j'ai implémenté une classification simple à deux classes dans Keras. Il semble y avoir un moyen d'utiliser la fonction softmax (l'article présenté au début était principalement implémenté dans softmax), donc je pensais l'écrire aussi, mais comme c'est devenu un peu plus, j'aimerais saisir une autre opportunité pense.
Recommended Posts