UTL_NLA
durchgeführt wird. UTL_NLA
stellt dazu BLAS
(Basic Linear Algebra Subroutines) und LAPACK
(Linear Algebra PACKage) bereit.Wie im vorherigen Post zu diesem Thema, werden die folgenden Daten verwendet:
y = Nachgefragte Menge in 1000 Stück
x1 = Werbeausgaben in 100.000 Euro für Printmedien
x2 = Werbeausgaben in 100.000 Euro für Fernsehen
x3 = Preis pro Mengeneinheit in 100 Euro
y | x1 | x2 | x3 |
---|---|---|---|
500 | 1 | 1 | 20 |
800 | 3 | 1 | 20 |
1500 | 3 | 3 | 18 |
2500 | 6 | 4 | 15 |
3200 | 6 | 6 | 12 |
Man erhält die Koeffizienten der Regressionsfunktion in Form des Vektors b durch:
Die Matrix X im Beispiel:
Der Vektor y im Beispiel:
Die Berechnung des Vektors b umfasst also die Bestimmung der Inversen, die Multiplikation von Matrizen und die Multiplikation einer Matrix mit einem Vektor. All diese Operationen lassen sich mithilfe von
UTL_NLA
durchführen. Für die Multiplikation von Matrizen wird BLAS_GEMM
verwendet, für die Multiplikation einer Matrix mit einem Vektor wird BLAS_GEMV
verwendet und für die Lösung des Gleichungssystems kommt LAPACK_GESV
zum Einsatz.Die Werte für die Matrizen werden entweder Zeilen- oder Spaltenweise angeben, je nachdem für welches Argument man sich für den Parameter PACK entscheidet. Im folgenden Beispiel wurde als Argument für den Parameter PACK 'R' gewählt. Die Deklaration stellt sich dann wie folgt dar:
v_matrix_xt UTL_NLA_ARRAY_DBL := UTL_NLA_ARRAY_DBL( 1 , 1 , 1 , 1 , 1, 1 , 3 , 3 , 6 , 6, 1 , 1 , 3 , 4 , 6, 20, 20, 18, 15, 12 ); v_matrix_x UTL_NLA_ARRAY_DBL := UTL_NLA_ARRAY_DBL( 1 , 1 , 1 , 20, 1 , 3 , 1 , 20, 1 , 3 , 3 , 18, 1 , 6 , 4 , 15, 1 , 6 , 6 , 12 );Der Aufruf der Prozedur
UTL_NLA.BLAS_GEMM
ermittelt nun die Matrix XTX.UTL_NLA.BLAS_GEMM( transa => 'N', transb => 'N', m => 4, n => 4, k => 5, alpha => 1, a => v_matrix_xt, lda => 5, b => v_matrix_x, ldb => 4, beta => 0, c => v_matrix_xtx, ldc => 4, pack => 'R');Nun wird der Vektor XTy mithilfe von
UTL_NLA.BLAS_GEMV
bestimmt:UTL_NLA.BLAS_GEMV( trans => 'N', m => 4, n => 5, alpha => 1, a => v_matrix_xt, lda => 5, x => v_vector_y, incx => 1, beta => 0, y => v_vector_xty, incy => 1, pack => 'R');Im finalen Schritt, zur Bestimmung der Koeffizienten, ist das folgende Gleichungssystem zu lösen:
XTXb=XTy
Diese Aufgabe erledigt die Prozedur
UTL_NLA.LAPACK_GESV
, wobei sich das Ergebnis nach dem Aufruf in der Variablen befindet, die als Argument für den Parameter b übergeben wurde.UTL_NLA.LAPACK_GESV( n => 4, nrhs => 1, a => v_matrix_xtx, lda => 4, ipiv => v_matrix_p, b => v_vector_xty, ldb => 1, info => v_result, pack => 'R');Die Ausgabe der Koeffizienten ergibt:
for i in 1..v_vector_xty.count loop dbms_output.put_line('b' || (i-1) || ' = ' || to_number(v_vector_xty(i))); end loop; b0 = 1440.8163265303169 b1 = 168.36734693877926 b2 = 266.32653061226313 b3 = -69.38775510202751Die Regressionsfunktion ergibt sich somit zu:
y = 1440,8163 + 168,3673∙x1 + 266,3265∙x2 - 69,3878∙x3
Abschließend sei noch erwähnt, dass eine Matrix bzw. ein Vektor vom Typ
UTL_NLA_ARRAY_DBL
bzw. UTL_NLA_ARRAY_FLT
maximal 1.000.000 Elemente enthalten kann.Natürlich befinden sich die Daten meist in einer Tabelle und man will die Matrix nicht manuell angeben. Vielmehr möchte man die Elemente durch SQL und PL/SQL gewinnen und in einer Variablen vom entsprechenden Typ speichern.
Aber das ist was für einen anderen Post...
Hi, leider funktioniert deine Beispiel seit Version 10.2g so nicht mehr. Der erste Aufruf von BLAS_GEMM konnte ich zum Laufen bekommen mit dem Parametern transa->T und transb->T.
AntwortenLöschenDie Funktion BLAS_GEMV scheint überhaupt nicht mehr zu wollen, da kann man tun was man will, stützt immer ab.
vielleicht hast du eine Idee wie man dein Beispiel wieder zum Laufen bekommt?
Danke für deine Meinung / Hilfe und beste Grüsse
In der Funktion GEMV muss lda auf 4 statt 5 stehen?
AntwortenLöschenUTL_NLA.BLAS_GEMV(
trans => 'N',
m => 4,
n => 5,
alpha => 1,
a => v_matrix_xt,
lda => 5,
x => v_vector_y,
incx => 1,
beta => 0,
y => v_vector_xty,
incy => 1,
pack => 'R');
jetzt kämpfe ich noch mit GESV:
AntwortenLöschenUTL_NLA.LAPACK_GESV(n => 4,
nrhs => 1,
a => v_matrix_xtx,
lda => 4,
ipiv => v_matrix_p,
b => v_vector_xty,
ldb => 1,
info => v_result,
pack => 'R');
das stürzt auch noch ab.
Habe jetzt als Zwischenresultate folgende Matrix:
Anzahl v_matrix_x: 20
Anzahl v_matrix_xtx: 16
Anzahl v_vector_xty: 4
Parameter ldb von UTL_NLA.LAPACK_GESV angepasst:
AntwortenLöschen--alt : ldb => 1,
--neu : ldb => 4,
Mit dem Resultat, dass das Skript mal läuft, allerdings kommen nun nicht die gleichen Koeffizienten raus, aber ich werde jetzt nachdem es läuft, mal meine Werte einsetzen und mit dem Excel vergleichen....
Vielen Dank schon mal für den grunsätzlichen Lösungsweg