Matrixen

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

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
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

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
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

@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/
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

@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.
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

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>
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

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>
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

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.
Benutzeravatar
__blackjack__
User
Beiträge: 13068
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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]]
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

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.
Benutzeravatar
__blackjack__
User
Beiträge: 13068
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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‽
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

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.
Benutzeravatar
__blackjack__
User
Beiträge: 13068
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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))
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten