Seite 1 von 1

Matrixen

Verfasst: Dienstag 26. März 2019, 20:16
von Hypec
Hallo,
mein Ziel ist es mit diesem Code 2 Matrixen zu generieren und dann zu addieren. Das Problem ist in Schritt 3 bekommt auf einmal die Matrixe m die gleichen Werte wie m2 obwohl ja eigentlich nur zu jeder Zahl eine 1 addiert werden soll. Weiß jemand was ich hier Falsch mache?

Code: Alles auswählen

import matrix

def main():
    Matrix = matrix.matrix()
    m = Matrix.Matrix(3,2)
    m2 = Matrix.Matrix(3,2)
    print(m)
    print(m2)
    print('schritt 1')
    #m = Matrix.randomize()
    m2 = Matrix.randomize()
    print(m)
    print(m2)
    print('schritt 2')
    m = Matrix.add(1)
    print(m)
    print(m2)
    print('schritt 3')
    m2 = Matrix.add(m)
    print(m2)
    

main()

Code: Alles auswählen

import random
import numpy as np

class matrix:

    def Matrix(self, rows=2, cols=2):
        self.rows = rows
        self.cols = cols
        self.matrix = np.zeros(shape=(rows,cols))          

        return self.matrix

    def randomize(self):
        for i in range(self.rows):
            for j in range(self.cols):
                self.matrix[i][j] = random.randint(0, 10)
        return self.matrix
    
    def add(self, n):
        m = np.zeros(shape=(1,1))
        if type(n) == type(m):
            for i in range(self.rows):
                for j in range(self.cols):
                    self.matrix[i][j] += n[i][j]   
        else:
            for i in range(self.rows):
                for j in range(self.cols):
                    self.matrix[i][j] += n         
        return self.matrix

    def scale(self, n):
        for i in range(self.rows):
            for j in range(self.cols):
                self.matrix[i][j] *= n
        return self.matrix

Re: Matrixen

Verfasst: Dienstag 26. März 2019, 20:45
von __deets__
Vor allem machst du einen Fehler indem du numpy nicht benutzt. Von grundlegenden Verständnisproblemen bei der Nutzung von Klassen angesehen, kannst du dir die ganzen mühselig programmierten und langsamen Operationen sparen, und einfach direkt zwei numpy Objekte addieren. Oder skalieren.

Code: Alles auswählen

a = numpy.ones((2, 3)) 
a *= 3

Re: Matrixen

Verfasst: Dienstag 26. März 2019, 21:25
von ThomasL
@deets ich gehe davon aus, dass Hypec die Tutorials von The Coding Train, die in Java/Javascript sind, genauso wie ich vor 1 Jahr, in Python
nach programmiert. Sehr empfehlenswert. So bekommt man ein grundlegendes Verständnis wie Neuronale Netze / Perceptrons funktionieren.
Ohne das jetzt ausprobiert zu haben, ist die Initialisierung der Klasse hier ein Problem.

Code: Alles auswählen

class matrix:

    def Matrix(self, rows=2, cols=2):
        self.rows = rows
        self.cols = cols
        self.matrix = np.zeros(shape=(rows, cols))          

        return self.matrix
sollte lauten

Code: Alles auswählen

class matrix:

    def __init__(self, rows=2, cols=2):
        self.rows = rows
        self.cols = cols
        self.matrix = np.zeros(shape=(rows, cols))          

@Hypec
schau mal hier rein
https://realpython.com/courses/intro-ob ... op-python/

Re: Matrixen

Verfasst: Dienstag 26. März 2019, 21:29
von __deets__
@ThomasL: das habe ich mir schon gedacht. Aber dabei muss man ja nun nicht Dinge ums verrecken schlechter machen, als sie einfach so schon gehen. Eine Matrix zu addieren kann numpy halt schon. Und das Verständnis von NN wird davon ja nicht besser.

Re: Matrixen

Verfasst: Mittwoch 27. März 2019, 15:17
von Hypec
Ja ich bearbeite die Tutorials von The Coding Train. Das ganze aufwändige addieren hab ich angefangen weil ich versucht habe mit so wening Libarys wie möglich zu arbeiten. Da es funktioniert habe ich es so gelassen als ich angefangen habe numpy zu nützen.

Das mit def __init__ habe ich auch schon Probiert allerdings bekomme ich dann keine Matrix mehr zurück.
Sondern so etwas:

Code: Alles auswählen

<matrix.matrix object at 0x000001BFA591E588>
<matrix.matrix object at 0x000001BFA591EA58>

Re: Matrixen

Verfasst: Mittwoch 27. März 2019, 15:26
von __deets__
Das ist deine matrix. Wenn du deine Klasse (entgegen der Konvention) matrix klein schrieben nennst, und die in einem Modul matrix steckt, dann heisst einen Instanz davon <matrix.matrix object at adresse>

Re: Matrixen

Verfasst: Mittwoch 27. März 2019, 16:48
von Hypec
Das mit der Konvention wusste ich nicht. Aber das ändert auch nichts daran das ich keine Matrix mehr zurückbekomme sondern eine Instanz mit der ich so recht Wenig anfangen kann.

Re: Matrixen

Verfasst: Mittwoch 27. März 2019, 16:54
von __blackjack__
@Hypec: Doch Du bekommst eine Matrix zurück. Wenn die `repr()`-Darstellung davon anders aussehen soll, zum Beispiel den Inhalt der Matrix enthalten soll, dann musst Du das halt entsprechend programmieren, also eine `__repr__()`-Methode implementieren. Oder das `attr`-Modul verwenden und das die `__repr__()` für Dich schreiben lassen.

Oder Du benutzt die Numpy-Objekte. Die haben nicht nur die Rechenoperationen schon implementiert, sondern auch eine `__repr__()`. Durch das nicht-nutzen von Numpy machst Du Dir nur unnötig Arbeit.

Edit: Dein Beispiel im ersten Beitrag ohne unnötige zusätzliche eigene Matrix-Klasse:

Code: Alles auswählen

#!/usr/bin/env python3
import numpy as np


def main():
    m = np.zeros((3, 2), int)
    m2 = np.zeros((3, 2), int)
    print(m)
    print(m2)
    print('schritt 1')
    m2 = np.random.randint(10, size=(m2.shape))
    print(m)
    print(m2)
    print('schritt 2')
    m += 1
    print(m)
    print(m2)
    print('schritt 3')
    m2 += m
    print(m2)


if __name__ == '__main__':
    main()
Ausgabe:

Code: Alles auswählen

[[0 0]
 [0 0]
 [0 0]]
[[0 0]
 [0 0]
 [0 0]]
schritt 1
[[0 0]
 [0 0]
 [0 0]]
[[7 6]
 [3 7]
 [3 5]]
schritt 2
[[1 1]
 [1 1]
 [1 1]]
[[7 6]
 [3 7]
 [3 5]]
schritt 3
[[8 7]
 [4 8]
 [4 6]]

Re: Matrixen

Verfasst: Donnerstag 28. März 2019, 16:51
von Hypec
Das ganze war nur um den Code zu testen das ich das nicht immer Eingeben muss also ich will eigentlich schon mit der Klasse weiter arbeiten.
Aber danke für deine Hilfe dann schreib ich die Klasse jetzt mit repr() und numpy.

Re: Matrixen

Verfasst: Donnerstag 28. März 2019, 17:06
von __blackjack__
@Hypec: Warum willst Du mit Klassen arbeiten? Also ich meine jetzt im speziellen mit einer Klasse die effektiv das gleiche macht/kann wie die Klasse `array` aus Numpy? Ich könnte das verstehen wenn man es ohne Numpy machen möchte, um mal zu sehen wie man eine Matrix als Datentyp selber implementiert, aber wenn die Matrix-Implementierung sich selbst auf eine bereits vorhandene abstützt, lernt man doch auch nicht wirklich etwas‽

Re: Matrixen

Verfasst: Donnerstag 28. März 2019, 17:17
von Hypec
Ich will das ganze so machen das ich es einfach nutzen kann und später dann eigentlich über Inputs regeln kann, was jetzt mit den Matrixen gemacht wird. Außerdem wollte ich numpy ursprünglich nur wegen des Datentypes nutzen das ich schauen kann was ich addieren will.

Re: Matrixen

Verfasst: Donnerstag 28. März 2019, 17:35
von __blackjack__
@Hypec: Bei Deine Klasse ist neben der fehlenden `__init__()` auch falsch, das Du überall die interne Matrix als Rückgabewert hast, was die ”Methoden” zu einer komischen Mischung aus Methode und Funktion macht die Numpy-Arrays zurück geben, also letztendlich arbeitest Du dann sowieso schon mit Numpy-Arrays.

Was man ja auch am Argument von `add()` sieht: Du testest nicht ob das ein Exemplar *Deiner* Klasse ist, sondern ob das ein Numpy-Array ist. Wobei man, wenn man schon auf Typen testen muss, nicht `type()` und ``==`` verwendet, sondern `isinstance()`. Man muss auch kein Array mit einer Zeile/Spalte erstellen nur um den Typ zu bekommen – der ist ja bekannt: `numpy.ndarray`.

Dass das Attribut eines `Matrix`-Objekts selbst wieder `matrix` heisst, ist auch wieder so eine Art Alarmzeichen, denn eine Matrix enthält keine Matrix sondern Werte.

Die `__init__()` über die Anzahl der Zeilen und Spalten zu regeln erschwert es eine typische `__repr__()`-Darstellung zu implementieren, weil man damit ja nur Matrizen erstellen kann, die überall 0 als Wert haben. Man würde also eher die Zeilen- und Spalten-Variante in eine Klassenmethode verlagern.

`rows` und `cols` als Attribute sind redundant, weil diese Information ja schon in `shape` vom Numpy-Array steckt.

Die Klasse aus dem Ausgangsbeispiel würde in Python das also eher so aussehen (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
import numpy as np


class Matrix:

    def __init__(self, values):
        self.values = values

    def __repr__(self):
        return f'{self.__class__.__name__}({self.values!r})'

    @property
    def rows(self):
        return self.values.shape[0]
    
    @property
    def cols(self):
        return self.values.shape[1]

    def randomize(self):
        self.values = np.random.randint(0, 10, self.values.shape)
    
    def add(self, other):
        if isinstance(other, Matrix):
            other = other.values
        self.values = self.values + other

    def scale(self, factor):
        self.values = self.values * factor

    @classmethod
    def from_shape(cls, rows, cols):
        return cls(np.zeros((rows, cols), int))