Formatera data för TensorFlow
Del 1 av denna bloggserie visade fördelarna med att använda en relationsdatabas för att lagra och utföra datautforskning av bilder med enkla SQL-satser. I den här handledningen, del 2, kommer data som används i del ett att nås från en MariaDB Server-databas och konverteras till de datastrukturer som behövs av TensorFlow. Resultaten av att använda modellen för att klassificera nya bilder kommer att lagras i en relationstabell för vidare analys.
Det här är en snabb handledning av ett TensorFlow-program med detaljerna som beskrivs medan vi går. Om du inte är bekant med de grundläggande begreppen är ett bra ställe att börja denna TensorFlow-handledning, "Grundläggande klassificering:Klassificera bilder av kläder". Några av exemplen och koden i handledningen används här.
Ytterligare paket behövs
Några ytterligare paket behövs för att bygga och träna bildklassificeringsmodellen:
- Pickle implementerar binära protokoll för serialisering och avserialisering av en Python-objektstruktur.
- NumPy ger stöd för stora, flerdimensionella arrayer och matriser, tillsammans med matematiska funktioner på hög nivå för att arbeta på dessa arrayer.
- TensorFlow är ett Python-bibliotek för snabb numerisk beräkning. Det är ett grundbibliotek som kan användas för att skapa Deep Learning-modeller direkt eller genom att använda wrapper-bibliotek som förenklar processen som byggs ovanpå TensorFlow.
- Keras är ett neuralt nätverksbibliotek med öppen källkod skrivet i Python.
importera pickleimport numpy som npimport tensorflow som tffrom tensorflow import kerasprint('Tensorflow version:', tf.__version__)print('Numpy version:', np.__version__)Tensorflow version:2.0.0Numpy version:1.16.2Hämta bilder
När paketen har importerats är nästa steg att hämta träningsbilderna från databasen och dela upp data i två numpy matriser. Först måste vi initiera träningsbilderna (train_images) och träningsetiketter (train_labels) arrayer. Eftersom vi redan har vektoriserat bilderna kan vi använda img_vector-attributet för att fylla i arrayen train_images med SQL-satsen nedan.
# Initialize the numpy arraystrain_images =np.empty((60000,28,28), dtype='uint8')train_labels =np.empty((60000), dtype='uint8')# Hämta träningsbilderna från databasesql="VÄLJ img_label, img_vector, img_idx \FROM tf_images INNER JOIN img_use ON img_use =use_id \WHERE use_name ='Träning'"cur.execute(sql)result =cur.fetchall()# Fyll i de numpy arrayerna. rad[2] innehåller bildindex för rad i result:nparray =pickle.loads(row[1])train_images[rad[2]] =nparraytrain_labels[rad[2]] =rad[0]På liknande sätt kan bilderna för testning hämtas från databasen. numpy arrayer som används i det här fallet är test_images och test_labels. I det här fallet är testdata 10 000 bilder med en upplösning på 28×28 pixlar.
# Initiera de numpy arraystest_images =np.empty((10000,28,28), dtype='uint8')test_labels =np.empty((10000), dtype='uint8')# Hämta testbilderna från databasesql="VÄLJ img_label, img_vector, img_idx \FROM tf_images INNER JOIN img_use ON img_use =use_id \WHERE use_name ='Testing'"cur.execute(sql)result =cur.fetchall()# Fyll i de numpy arrayerna. rad[2] innehåller bildindexet för rad i result:nparray =pickle.loads(row[1])test_images[rad[2]] =nparraytest_labels[rad[2]] =rad[0]Slutligen mappas varje bild till en enda etikett. Etikettnamnen lagras i kategoritabellen och läses in i arrayen class_names:
sql="SELECT class_name FROM categories"cur.execute(sql)class_names =cur.fetchall()Förbehandla data
Data måste förbehandlas innan nätverket tränas. Om du inspekterar den första bilden i träningssetet kommer du att se att pixelvärdena faller inom intervallet 0 till 255:
plt.figure()plt.imshow(train_images[0])plt.colorbar()plt.grid(False)plt.show()
ovan:bild från fashion_mnist datasetInnan bilderna matas till den neurala nätverksmodellen måste värdena skalas till ett intervall från 0 till 1. För att göra det, dividera värdena med 255. Det är viktigt att träningssetet och testsetet är förbehandlade på samma sätt .
Du kan använda matplotlib för att visa de första 25 bilderna för att verifiera att data är i rätt format och redo för att bygga och träna nätverket:
train_images =train_images / 255.0test_images =test_images / 255.0plt.figure(figsize=(10,10))for i in range(25):plt.subplot(5,5,i+1)plt.xticks([ ])plt.yticks([])plt.grid(False)plt.imshow(train_images[i], cmap=plt.cm.binary)plt.xlabel(class_names[train_labels[i]])plt.show()
ovan:bilder från fashion_mnist datasetBygga modellen
Efter att data har förbehandlats till två delmängder kan du fortsätta med en modellträning. Denna process innebär att "mata" algoritmen med träningsdata. Algoritmen kommer att bearbeta data och mata ut en modell som kan hitta ett målvärde (attribut) i ny data – det vill säga klassificera bilden som presenteras för det neurala nätverket.
De flesta neurala nätverk för djupinlärning skapas genom att enkla lager kedjas samman.
Det första lagret i nätverket omvandlar bildformatet från en tvådimensionell array (med 28 gånger 28 pixlar) till en endimensionell array (på 28 * 28 =784 pixlar). Det här lagret har inga parametrar att lära sig; den formaterar bara om data.
Efter att pixlarna är tillplattade består nätverket av två helt anslutna lager som måste aktiveras. I ett neuralt nätverk är aktiveringsfunktionen ansvarig för att omvandla den summerade viktade ingången från noden till aktiveringen av noden eller utgången för den ingången.
Det första täta lagret har 128 noder (eller neuroner) och använder en Rectified Linear Unit (ReLU) aktiveringsmetod. Den likriktade linjära aktiveringsfunktionen är en bitvis linjär funktion som matar ut ingången direkt om den är positiv, annars kommer den att mata ut noll.
Det andra (och sista) lagret är ett softmax-lager med 10 noder. En softmax-funktion matar ut en vektor som representerar sannolikhetsfördelningarna för en lista med potentiella utfall. Den returnerar en matris med 10 sannolikhetspoäng som summerar till 1. Varje nod innehåller en poäng som anger sannolikheten att den aktuella bilden tillhör en av de 10 klasserna.
De flesta lager, som tf.keras.layers.Dense, har parametrar som lärs in under träningen.
model =keras.Sequential([keras.layers.Flatten(input_shape=(28, 28)),keras.layers.Dense(128, activation='relu'),keras.layers.Dense(10, activation='softmax')])Kompilerar modellen
Modellkompileringssteget används för att lägga till några fler inställningar innan den är redo för träning. I det här fallet är följande inställningar aktiverade.
- Optimerare – uppdaterar modellen baserat på data den ser och dess förlustfunktion (se nedan).
- Förlustfunktion – mäter hur exakt modellen är under träning. Du vill minimera denna funktion för att "styra" modellen i rätt riktning.
- Mätvärden – Övervaka tränings- och teststegen. Följande exempel använder noggrannhet, den del av bilderna som är korrekt klassificerade.
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['precision'])Utbildning av modellen
Att träna den neurala nätverksmodellen kräver följande steg.
- Mata träningsdata till modellen.
- Modellen lär sig att associera bilder och etiketter.
- Gör förutsägelser om en testuppsättning.
- Verifiera att förutsägelserna matchar etiketterna från arrayen test_labels.
För att börja träna, anropa metoden model.fit – så kallad eftersom den "passar" modellen till träningsdata:
model.fit(train_images, train_labels, epochs=10)Träna på 60000 proverEpoch 1/1060000/60000 [==============================] - 5s 83us/prov - förlust:0,4964 - noggrannhet:0,8236Epoch 2/1060000/60000 [===============================] - 4s 65us/prov - förlust:0,3735 - noggrannhet:0,8642Epoch 3/1060000/60000 [===============================] - 3s 55us/prov - förlust:0,3347 - noggrannhet:0,8773Epoch 4/1060000/60000 [================================] - 3s 56us/prov - förlust:0,3106 - noggrannhet:0,8861Epoch 5/1060000/60000 [================================] - 3s 58us/prov - förlust:0,2921 - noggrannhet:0,8924s - förlust:0,2928 - noggrannhet - ETA:0s - förlust:0,2925 - noggrannhetEpoch 6/1060000/6000================================] - 3s 57us/prov - förlust:0,2796 - noggrannhet:0,8969sEpoch 7/1060000/60000 [==============================] - 4s 70us/prov - förlust:0,2659 - noggrannhet:0,9007Epoch 8/1060000/60000 [==============================] - 4s 61us/prov - förlust:0,2548 - noggrannhet:0,9042Epoch 9/1060000/60000 [ ===============================] - 4s 61us/prov - förlust:0,2449 - noggrannhet:0,9084Epoch 10/1060000/60000 [==============================] - 5s 76us/prov - förlust:0,2358 - noggrannhet:0,9118I slutet av varje epok utvärderas det neurala nätverket mot valideringsuppsättningen. Detta är vad förlust och noggrannhet syftar på.
Utvärdera noggrannheten och förutsäga
För att uppskatta modellens övergripande noggrannhet, beräkna medelvärdet av alla tio förekomster av noggrannhetsvärdet, i detta fall 88 %.
Kör sedan model.evaluate på testsetet för att få den prediktiva noggrannheten hos det tränade neurala nätverket på tidigare osynliga data.
test_loss, test_acc =model.evaluate(test_images, test_labels, verbose=2)10000/1 - 0s - förlust:0,2766 - noggrannhet:0,8740Testdatauppsättningen är mindre exakt än träningsdatauppsättningen. I det här fallet representerar detta gap mellan träningsnoggrannhet och testnoggrannhet överanpassning. Motsatsen är underfitting. Om du vill lära dig mer om detta ämne rekommenderar jag Overfitting vs. Underfitting:A Conceptual Explanation av Will Koehrsen.
Vid det här laget kan vi göra några förutsägelser om bilderna i vår träningsdatauppsättning.
predictions =model.predict(test_images)predictions[0]array([1.90860412e-08, 8.05085235e-11, 1.56402713e-08, 1.66699390e-10,7.8693-30.69e,6699390e-10,7.869330.69e -08, 1.20656565e-02,3.80084719e-09, 9.87929940e-01], dtype=float32)Utdata från model.predict är en matris med 10 nummer med sannolikheten att en instans tillhör varje klass. Att bevara resultaten i MariaDB-databasen för vidare analys och rapportering är en bra idé. Nedan är ett exempel på hur man itererar på prediktionsarrayen för att bygga en tupel och sedan infogar den i prediction_results bord.
sql ="INSERT INTO prediction_results (img_idx, img_use, T_shirt_Top, Trouser, Pullover, Dress, Coat, Sandal, Shirt, Sneaker, Bag, Ankle_boot, label)VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s);"i =0för rad i förutsägelser:insert_tuple =(str(i), str(2), str (rad[0]), str(rad[1]), str(rad[2]), str(rad[3]), str(rad[4]), str(rad[5]), str(rad [6]), str(rad[7]), str(rad[8]), str(rad[9]), str(test_etiketter[i]))cur.execute(sql, insert_tuple)conn.commit() i +=1Återigen kan en enkel SQL-sats användas för att verifiera att data har laddats.
sql ="VÄLJ T_shirt_Top, Byxa, Pullover, Klänning, Kappa, Sandal, Skjorta, Sneaker, Väska, Ankle_boot, class_name som 'Test Label'FROM prediction_results JOIN-kategorier PÅ label =class_idx WHERE img_idx =1"display( pd. read_sql(sql,conn) )
T_shirt_Top | Byxa | Tröja | Klänning | rock | Sandal | Tröja | Sneaker | Väska | Ankel_boot | Testetikett |
0,00001 | 0.0 | 0,997912 | 0.0 | 0,001267 | 0.0 | 0,00081 | 0.0 | 0.0 | 0.0 | Tröja |
Plotta förutsägelser
Ett par plottningsfunktioner för att visa förutsägelserna definieras nedan (graffunktioner).
Låt oss hämta en ny bild från testsetet och visa den neurala nätklassificeringen baserat på prediktionssannolikheten.
sql ="SELECT img_idx, label FROM prediction_results WHERE img_idx =1"cur.execute(sql)result =cur.fetchone()plt.figure(figsize=(6,3))plt.subplot(1,2, 1)plot_image(result[0], predictions[result[0]], test_labels, test_images)plt.subplot(1,2,2)plot_value_array(result[0], predictions[result[0]], test_labels)plt. show()
ovan:bild från fashion_mnist dataset
I det här fallet kunde modellen klassificera bilden korrekt med 100 % noggrannhet. Låt oss sedan köra en fråga för att hämta de första 15 bilderna från testsetet och klassificera dem.
sql ="SELECT img_idx, label FROM prediction_results LIMIT 15"num_rows =5num_cols =3plt.figure(figsize=(2*2*num_cols, 2*num_rows))cur.execute(sql)result =cur.fetchall() för rad i resultat:plt.subplot(antal_rader, 2*antal_kol, 2*rad[0]+1)plot_image(rad[0], förutsägelser[rad[0]], test_etiketter, test_bilder)plt.subplot(antal_rader, 2 *antal_cols, 2*row[0]+2)plot_value_array(row[0], predictions[row[0]], test_labels)plt.tight_layout()plt.show()
ovan:bilder från fashion_mnist dataset
Som du kan se kommer det att finnas tillfällen där modellen kan ha fel som visas i sista raden, vänster kolumn. I det här fallet klassades en sneaker som en sandal (i rött).
Sammanfattning
Även om integrationen mellan TensorFlow och MariaDB Server är enkel, är fördelarna med denna integration betydande:
- Användning av relationsdata inom maskininlärning kan minska implementeringskomplexiteten. Både dataforskare och dataingenjörer kan använda ett gemensamt språk för att utföra datatvistar och utforskningsuppgifter.
- Effektivitet som uppnås när du kommer åt, uppdaterar, infogar, manipulerar och modifierar data kan påskynda tiden till marknaden.
- Möjligheten att lagra resultaten av modellen tillbaka till databasen gör det möjligt för slutanvändare och analytiker att utföra frågor och rapporter med vänliga rapporteringsverktyg som Tableau.
MIT-licens
Uppsättningen Fashion MNIST (fashion_mnist) som utnyttjas av den här bloggen är licensierad under MIT-licensen, Copyright © 2017 Zalando SE, https://tech.zalando.com
Källkoden som används av den här bloggen är anpassad från handledningen "Grundläggande klassificering:Klassificera bilder av kläder" som är licensierad under MIT-licensen, Copyright (c) 2017 François Chollet.
Tillstånd ges härmed kostnadsfritt till varje person som skaffar en kopia av denna programvara och tillhörande dokumentationsfiler ("Programvaran") att handla med programvaran utan begränsningar, inklusive utan begränsning rätten att använda, kopiera, modifiera, slå samman , publicera, distribuera, underlicensiera och/eller sälja kopior av programvaran, och för att tillåta personer till vilka programvaran tillhandahålls att göra det, med förbehåll för följande villkor:
Ovanstående copyrightmeddelande och detta tillståndsmeddelande ska inkluderas i alla kopior eller väsentliga delar av programvaran.
PROGRAMVARAN TILLHANDAHÅLLS "I BEFINTLIGT SKICK", UTAN GARANTIER AV NÅGOT SLAG, UTTRYCKTA ELLER UNDERFÖRSTÅDDA, INKLUSIVE MEN INTE BEGRÄNSAT TILL GARANTIER FÖR SÄLJBARHET, LÄMPLIGHET FÖR ETT SÄRSKILT ÄNDAMÅL OCH INTRÄNG. UNDER INGA OMSTÄNDIGHETER SKALL FÖRFATTARE ELLER UPPHOVSRÄTTSinnehavare VARA ANSVARIGA FÖR NÅGOT ANSVAR, SKADA ELLER ANNAT ANSVAR, VARKEN I EN ANVÄNDNING AV KONTRAKT, TORT ELLER ANNAT SÄTT, SOM UPPSTÅR FRÅN, UR ELLER I SAMBAND MED ANVÄNDNINGEN ELLER MJUKVARAN. PROGRAMVARA.
Referenser
Konvertera egen bild till MNIST:s bild
matplotlib:Bildhandledning
5 sätt AI förvandlar kundupplevelsen
Digitalisering uppfinner verksamheten på nytt
Vad är bildklassificering?
Introduktion till Python Deep Learning Library TensorFlow
Plotta funktioner
def plot_image(i, predictions_array, true_label, img):predictions_array, true_label, img =predictions_array, true_label[i], img[i]plt.grid(False)plt.xticks([])plt.yticks([ ])plt.imshow(img, cmap=plt.cm.binary)predicted_label =np.argmax(predictions_array)if predicted_label ==true_label:color ='blue'else:color ='red'plt.xlabel("{} { :2.0f}% ({})".format(class_names[predicted_label],100*np.max(predictions_array),class_names[true_label]),color=color)def plot_value_array(i, predictions_array, true_label):predictions_array, true_label =predictions_array, true_label[i]plt.grid(False)plt.xticks(range(10))plt.yticks([])thisplot =plt.bar(range(10), predictions_array, color="#777777")plt .ylim([0, 1])predicted_label =np.argmax(predictions_array)thisplot[predicted_label].set_color('red')thisplot[true_label].set_color('blue')