SOM (self-organising map)
-
- User
- Beiträge: 73
- Registriert: Freitag 15. März 2013, 19:38
Wieso werden 3 Argumente gefordert, wenn es nur a und b als Parameter gibt?
Zuletzt geändert von barisoezcan am Freitag 15. März 2013, 20:48, insgesamt 2-mal geändert.
@barisoezcan: Weil es noch ein Argument gibt: `self`. Du erstellst ein Exemplar vom Typ `SOM` und machst damit überhaupt nichts. Du wolltest das vielleicht an einen Namen binden und dann darauf die Methode aufrufen, statt die (ungebundene) Methode auf der *Klasse* aufzurufen.
Allerdings machen weder Klasse noch ”Methode” hier Sinn. Warum steckst Du eine Funktion ohne dass das Sinn machen würde in eine Klasse?
Edit: Das ist übrigens kein Compiler-Fehler sondern ein Laufzeitfehler. Und das nächste mal könntest Du das alles vielleicht auch mit kopieren und einfügen als Text hier präsentieren, statt als Bild.
Allerdings machen weder Klasse noch ”Methode” hier Sinn. Warum steckst Du eine Funktion ohne dass das Sinn machen würde in eine Klasse?
Edit: Das ist übrigens kein Compiler-Fehler sondern ein Laufzeitfehler. Und das nächste mal könntest Du das alles vielleicht auch mit kopieren und einfügen als Text hier präsentieren, statt als Bild.
-
- User
- Beiträge: 73
- Registriert: Freitag 15. März 2013, 19:38
Du hast Recht.. Ich bin ein totaler Python-Neuling..
Das ist nur ein Ausschnitt aus einem Quellcode, der mich gestellt wurde..
Mit:
a = SOM()
print(a.calculateDistance(3, 7))
klappt es nun auch... Vielen Dank!
Das ist nur ein Ausschnitt aus einem Quellcode, der mich gestellt wurde..
Mit:
a = SOM()
print(a.calculateDistance(3, 7))
klappt es nun auch... Vielen Dank!
-
- User
- Beiträge: 73
- Registriert: Freitag 15. März 2013, 19:38
Weil in dieser Klasse noch ein paar weitere Methoden sind..BlackJack hat geschrieben:@barisoezcan: Erklärt immer noch nicht warum das eine Klasse ist.
Und die Klasse stellt eine SOM (self-organising map) dar...
Nachdem ich erst einmal verstanden habe wie sie funktionert, will ich sie testen.
-
- User
- Beiträge: 73
- Registriert: Freitag 15. März 2013, 19:38
Was für ein Datentyp könnte "data" sein?
...
Methode Anfang:
Methode Ende
...
"len(data[0])" deutet doch darauf hin, dass "data" eine Liste bzw. String ist, oder?..
Aber weiter unten läuft eine for-Schleife bis "data" und das deutet doch wiederum auf int hin..
...
Methode Anfang:
Code: Alles auswählen
def train(self, data, weights, dimensions, iterations, epsilon):
self.nodes = numpy.random.rand(self.size[0], self.size[1], len(data[0]))
self.weights = weights
self.epsilon = epsilon
for i in range(iterations):
for currentData in data: #training
self.trainNode(currentData)
...
"len(data[0])" deutet doch darauf hin, dass "data" eine Liste bzw. String ist, oder?..
Aber weiter unten läuft eine for-Schleife bis "data" und das deutet doch wiederum auf int hin..
@barisoezcan: ``len(data[0])`` deutet darauf hin das es eine Sequenz oder eine Abbildung ist die Elemente enthält die eine Länge haben, also wahrscheinlich selbst Container-Typen sind. Das ist alles was man daraus ersehen kann. Die Schleife geht nicht *bis* `data` sondern *über* `data`, über die einzelnen Elemente in `data`.
Vielleicht solltest Du mal ein Grundlagentutorial zu Python selbst und auch zu Numpy durcharbeiten. Das ist jeweils in den Dokumentationen zu finden.
Gibt es denn keine Dokumentation? Oder zumindest Aufrufe wo ersichtlich ist womit man die Methode aufrufen kann?
Vielleicht solltest Du mal ein Grundlagentutorial zu Python selbst und auch zu Numpy durcharbeiten. Das ist jeweils in den Dokumentationen zu finden.
Gibt es denn keine Dokumentation? Oder zumindest Aufrufe wo ersichtlich ist womit man die Methode aufrufen kann?
-
- User
- Beiträge: 73
- Registriert: Freitag 15. März 2013, 19:38
Wo kann ich denn hier ein vernünftiges Tutorium finden?
Und ja, das mit den for-Schleifen habe ich jetzt auch bemerkt.. und ist ein Unterschied
Da ich bislang nur ein wenig mit Java und C++ zu tun hatte, habe ich das beim überfliegen übersehen.
Und ja, das mit den for-Schleifen habe ich jetzt auch bemerkt..
Code: Alles auswählen
for x in range(y)
Code: Alles auswählen
for x in y
Da ich bislang nur ein wenig mit Java und C++ zu tun hatte, habe ich das beim überfliegen übersehen.
@barisoezcan: Wenn man schon ein wenig Programmiererfahrung hat, dann sollte man das Tutorial in der Python-Dokumentation mal durchgearbeitet haben. Das liefert einen ganz guten Überblick über die Programmiersprache. Einmal das Inhaltsverzeichnis der Bibliotheksreferenz durchgehen ist vielleicht auch eine gute Idee.
Bei Numpy gibt es auch ein Tutorial auf der Webseite vom Projekt verlinkt. Da ist insbesondere die „Slicing”-Syntax interessant, die sich anders verhält als „Slicing” bei den Grunddatentypen von Python. Und das man Operationen „parallel” auf alle Werte im Container anwenden kann und keine externen Schleifen dafür schreiben muss.
``for item in iterable: …`` in Python ist grundsätzlich wie ``for (Object item : iterable) { … }``. Syntax für eine Zählschleife a la ``for (int i = 0; i < n; i++) { … }`` gibt es in Python nicht.
Bei Numpy gibt es auch ein Tutorial auf der Webseite vom Projekt verlinkt. Da ist insbesondere die „Slicing”-Syntax interessant, die sich anders verhält als „Slicing” bei den Grunddatentypen von Python. Und das man Operationen „parallel” auf alle Werte im Container anwenden kann und keine externen Schleifen dafür schreiben muss.
``for item in iterable: …`` in Python ist grundsätzlich wie ``for (Object item : iterable) { … }``. Syntax für eine Zählschleife a la ``for (int i = 0; i < n; i++) { … }`` gibt es in Python nicht.
-
- User
- Beiträge: 73
- Registriert: Freitag 15. März 2013, 19:38
BlackJack hat geschrieben:@barisoezcan: Wenn man schon ein wenig Programmiererfahrung hat, dann sollte man das Tutorial in der Python-Dokumentation mal durchgearbeitet haben. Das liefert einen ganz guten Überblick über die Programmiersprache. Einmal das Inhaltsverzeichnis der Bibliotheksreferenz durchgehen ist vielleicht auch eine gute Idee.
Bei Numpy gibt es auch ein Tutorial auf der Webseite vom Projekt verlinkt. Da ist insbesondere die „Slicing”-Syntax interessant, die sich anders verhält als „Slicing” bei den Grunddatentypen von Python. Und das man Operationen „parallel” auf alle Werte im Container anwenden kann und keine externen Schleifen dafür schreiben muss.
``for item in iterable: …`` in Python ist grundsätzlich wie ``for (Object item : iterable) { … }``. Syntax für eine Zählschleife a la ``for (int i = 0; i < n; i++) { … }`` gibt es in Python nicht.
Vielen Dank für die kompetente Hilfe!
So wie ich das verstanden habe, wird die Schleife
Code: Alles auswählen
for x in b:
Stimmt das so?
@barisoezcan: Stimmt so. Wobei `b` ein beliebiges iterierbares Objekt sein kann. Das muss also kein Container-Objekt sein, sondern kann auch vorher unbekannt, bis unendlich viele, Elemente liefern.
Grundsätzlich würde ich aber von dem Gedanken, dass die Schleife n-mal durchlaufen wird, weggehen und allgemeiner sagen: Die Schleife läuft so lange, wie der Iterator für das Container-Objekt (oder exakter: das Iterable) noch Elemente ausspuckt. Die erweiterte `for`-Schleife in Java arbeitet ja letztlich auch mittels `it.hasNext()`-Abfragen auf einem Iterator und versucht nicht etwa, auf magische Weise vorab irgendeinen Endwert für `i` festzulegen. Man hat also überhaupt keinen Index-Zähler mehr, mit dessen Hilfe man noch den eigentlichen Zugriff tätigen müsste (`myObjects`), sondern bekommt in solchen Fällen direkt das jeweils nächste Objekt vom Iterator zurückgeliefert. Die `for`-Syntax ist so gesehen nur syntaktischer Zucker, um dem Programmierer das Leben etwas einfacher zu machen.
-
- User
- Beiträge: 73
- Registriert: Freitag 15. März 2013, 19:38
snafu hat geschrieben:Grundsätzlich würde ich aber von dem Gedanken, dass die Schleife n-mal durchlaufen wird, weggehen und allgemeiner sagen: Die Schleife läuft so lange, wie der Iterator für das Container-Objekt (oder exakter: das Iterable) noch Elemente ausspuckt. Die erweiterte `for`-Schleife in Java arbeitet ja letztlich auch mittels `it.hasNext()`-Abfragen auf einem Iterator und versucht nicht etwa, auf magische Weise vorab irgendeinen Endwert für `i` festzulegen. Man hat also überhaupt keinen Index-Zähler mehr, mit dessen Hilfe man noch den eigentlichen Zugriff tätigen müsste (`myObjects`), sondern bekommt in solchen Fällen direkt das jeweils nächste Objekt vom Iterator zurückgeliefert. Die `for`-Syntax ist so gesehen nur syntaktischer Zucker, um dem Programmierer das Leben etwas einfacher zu machen.
Hmm gute Erklärung Vielen Dank!
-
- User
- Beiträge: 73
- Registriert: Freitag 15. März 2013, 19:38
Code: Alles auswählen
import numpy
import math
import matplotlib.pyplot as plt
class SOM:
def __init__(self, size):
assert len(size) == 2
self.size = size
def train(self, data, weights, dimensions, iterations, epsilon):
self.nodes = numpy.random.rand(self.size[0], self.size[1], len(data[0]))
self.weights = weights
self.epsilon = epsilon
# plt.subplot(self.size[0], self.size[1], 1)
# plt.imshow(self.nodes.reshape(self.size[0], self.size[1], dimensions[0], dimensions[1])[3][3])
# plt.ion()
# plt.draw()
for i in range(iterations):
# if i % 1 == 0: # plot
# for x in range(self.size[0]):
# for y in range(self.size[1]):
# plt.title(str(i))
# plt.subplot(self.size[0], self.size[1], x + y * self.size[0] + 1)
# plot = plt.imshow(self.nodes.reshape(self.size[0], self.size[1], dimensions[0], dimensions[1])[x][y], interpolation="nearest")
# plot.axes.get_xaxis().set_visible(False)
# plot.axes.get_yaxis().set_visible(False)
# plt.draw()
# plt.show()
for currentData in data: #training
self.trainNode(currentData)
# plt.show()
input('Press Enter to exit')
def trainNode(self, data):
coordinate = self.findBestMatchingNode(data)
self.doTraining(data, coordinate)
def findBestMatchingNode(self, data):
bestDistance = float("nan")
result = [0, 0]
for x in range(self.size[0]):
for y in range(self.size[1]):
distance = self.calculateDistance(self.nodes[x][y], data)
if math.isnan(bestDistance) or distance < bestDistance:
bestDistance = distance
result = [x, y]
return result
def calculateDistance(self, a, b):
return numpy.sum(pow(a - b, 2) / (a + b))
def doTraining(self, data, coordinate):
for x in range(self.size[0]):
for y in range(self.size[1]):
f = 1 / (1 + pow(coordinate[0] - x, 2) + pow(coordinate[1] - y, 2))
self.nodes[x][y] = self.nodes[x][y] + self.weights[x][y] * self.epsilon * f * (data - self.nodes[x][y])
Ich bin gerade dabei sie zu analysieren und zu verstehen, aber komme leider an "data" nicht vorbei..
Da in Python die Variablen nicht explizit mit Datentypen deklariert werden, weiss ich nicht, was data (bzw. die Unterelemente der Unterelemente von "data", da "data" ein Containertyp zu sein scheint, die wiederum einen Containertyp enthält) für ein Datentyp sein könnte..
Ein paar Eckdaten:
Die SOM wird für Bilderkennung genutzt. Also gehe ich davon aus, dass "data" sowas wie die Bildpunktdaten enthalten könnte..
Das Auskommentierte ist eher unwichtig, da es zum Plotten verwendet wird.
Und es gibt leider keine Dokumentation oder Kommentare zum Quellcode.
Was mich noch ein wenig irritiert:
Die Elemente von "data" werden unverändert über verschiedene Methode bis zur Methode
Code: Alles auswählen
def calculateDistance(self, a, b):
return numpy.sum(pow(a - b, 2) / (a + b))
Wie ist das aber möglich, wenn doch die Elemente von "data" Containertypen sind?
@barisoezcan: Welches `data`? Es gibt da ja verschiedene. Da müsstest Du Dich am besten an den Aufrufen entlang bewegen und versuchen Erkenntnisse aus der Verwendung zu gewinnen. Man kann die Möglichkeiten ja einschränken. Wenn drüber iteriert wird, dann muss es ja iterierbar sein. Wenn Rechenoperationen mit bekannten Typen durchgeführt werden, wie zum Beispiel `self.nodes`, dann schränkt das die möglichen Formen ein. An der Stelle gehe ich mal davon aus, dass es sich Grundsätzlich einmal um `numpy`-Arrays handelt. Würde ja auch zu Bilddaten passen.
Andererseits würde ich das demjenigen um die Ohren hauen von dem es kommt. Selbst mit deklarierten Typen wäre das ohne weitere Erklärungen sehr wahrscheinlich nicht nutzbar ohne da so viel Analysearbeit hinein zu stecken mit der man es auch selbst hätte entwickeln können.
`numpy` benutzt es auch nicht wirklich gut. Da liesse sich sicher einiges an Schleifen aus dem Python-Code verbannen.
Andererseits würde ich das demjenigen um die Ohren hauen von dem es kommt. Selbst mit deklarierten Typen wäre das ohne weitere Erklärungen sehr wahrscheinlich nicht nutzbar ohne da so viel Analysearbeit hinein zu stecken mit der man es auch selbst hätte entwickeln können.
`numpy` benutzt es auch nicht wirklich gut. Da liesse sich sicher einiges an Schleifen aus dem Python-Code verbannen.
-
- User
- Beiträge: 73
- Registriert: Freitag 15. März 2013, 19:38
BlackJack hat geschrieben:@barisoezcan: Welches `data`? Es gibt da ja verschiedene. Da müsstest Du Dich am besten an den Aufrufen entlang bewegen und versuchen Erkenntnisse aus der Verwendung zu gewinnen. Man kann die Möglichkeiten ja einschränken. Wenn drüber iteriert wird, dann muss es ja iterierbar sein. Wenn Rechenoperationen mit bekannten Typen durchgeführt werden, wie zum Beispiel `self.nodes`, dann schränkt das die möglichen Formen ein. An der Stelle gehe ich mal davon aus, dass es sich Grundsätzlich einmal um `numpy`-Arrays handelt. Würde ja auch zu Bilddaten passen.
Andererseits würde ich das demjenigen um die Ohren hauen von dem es kommt. Selbst mit deklarierten Typen wäre das ohne weitere Erklärungen sehr wahrscheinlich nicht nutzbar ohne da so viel Analysearbeit hinein zu stecken mit der man es auch selbst hätte entwickeln können.
`numpy` benutzt es auch nicht wirklich gut. Da liesse sich sicher einiges an Schleifen aus dem Python-Code verbannen.
Hmm, ja dankeschön =) Bin jetzt ein großes Stück weitergekommen...
Allerdings tritt nun ein anderes Problem auf...
Ich habe die SOM versucht anzuwenden (mit 2 FITS-Bildern):
Code: Alles auswählen
import numpy
import pyfits
from SOM import SOM
#2 Bilder oeffnen
Bild1 = pyfits.open('Testbilder\Galaxie.fits')
pix1 = Bild1[0].data #Pixelwerte von Bild1
Bild2 = pyfits.open('Testbilder\Einschlaege.fits')
pix2 = Bild2[0].data #Pixelwerte von Bild2
#Beide Bilder haben die selbe Größe
data1 = []
for i in range(len(pix1)):
for j in range(len(pix1[0])):
data1.append(pix1[i][j]) #Die einzelnen Pixelwerte von Bild1 werden in eine Liste gepackt
data2 = []
for i in range(len(pix2)):
for j in range(len(pix2[0])):
data2.append(pix2[i][j]) #Die einzelnen Pixelwerte von Bild2 werden in eine Liste gepackt
#Initialisierungen
size = 1,2 #Anzahl der Nodes (2 Stück)
data = [a,b] #Bilddaten
weights = [[0.1 for i in range(size[1])] for i in range(size[0])] #Gewichtung
epsilon = 0.005 #Lernrate
iterations = 1000 #Iterationen
dimensions = len(pix1), len(pix1[0]) #Größe der Bilder
#Instanz der Klasse SOM
koh = SOM(size)
koh.train(data,weights,dimensions,iterations,epsilon)[0][0]
Das andere Bild wird sozusagen gar nicht berücksichtigt..
Aber es sollte ja eigentlich beim einen "Node" das eine Bild erscheinen, beim anderen "Node" das andere Bild (nach einer gewissen Anzahl von Iterationen) ...
Die beiden Bilder waren:
So sieht es dann aus:
Wie man erkennt, stellen die beiden Nodes nur das erste Bild dar..
Zuletzt geändert von barisoezcan am Sonntag 24. März 2013, 23:09, insgesamt 1-mal geändert.
-
- User
- Beiträge: 73
- Registriert: Freitag 15. März 2013, 19:38
Das wäre dann nochmal die komplette Klasse SOM, von der eine Instanz erzeugt wird...
Code: Alles auswählen
import numpy
import math
import matplotlib.pyplot as plt
class SOM:
def __init__(self, size):
assert len(size) == 2
self.size = size
def train(self, data, weights, dimensions, iterations, epsilon):
self.nodes = numpy.random.rand(self.size[0], self.size[1], len(data[0]))
self.weights = weights
self.epsilon = epsilon
plt.subplot(self.size[0], self.size[1], 1)
plt.imshow(self.nodes.reshape(self.size[0], self.size[1], dimensions[0], dimensions[1])[0][0])
plt.ion()
plt.draw()
for i in range(iterations):
if i % 1 == 0: # plot
for x in range(self.size[0]):
for y in range(self.size[1]):
plt.title(str(i))
plt.subplot(self.size[0], self.size[1], x + y * self.size[0] + 1)
plot = plt.imshow(self.nodes.reshape(self.size[0], self.size[1], dimensions[0], dimensions[1])[x][y], interpolation="nearest")
plot.axes.get_xaxis().set_visible(False)
plot.axes.get_yaxis().set_visible(False)
plt.draw()
plt.show()
for currentData in data: #training
self.trainNode(currentData)
plt.show()
input('Press Enter to exit')
def trainNode(self, data):
coordinate = self.findBestMatchingNode(data)
self.doTraining(data, coordinate)
def findBestMatchingNode(self, data):
bestDistance = float("nan")
result = [0, 0]
for x in range(self.size[0]):
for y in range(self.size[1]):
distance = self.calculateDistance(self.nodes[x][y], data)
if math.isnan(bestDistance) or distance < bestDistance:
bestDistance = distance
result = [x, y]
return result
def calculateDistance(self, a, b):
return numpy.sum(pow(a - b, 2) / (a + b))
def doTraining(self, data, coordinate):
for x in range(self.size[0]):
for y in range(self.size[1]):
f = 1 / (1 + pow(coordinate[0] - x, 2) + pow(coordinate[1] - y, 2))
self.nodes[x][y] = self.nodes[x][y] + self.weights[x][y] * self.epsilon * f * (data - self.nodes[x][y])