[PYTHON] Ich habe mit Swift eine N-dimensionale Matrixoperationsbibliothek Matft erstellt

Einführung

Dies ist der erste Beitrag. Wie der Titel schon sagt, habe ich mit Swift eine N-dimensionale Matrixoperationsbibliothek ** Matft (https://github.com/jjjkkkjjj/Matft) ** erstellt. Sah. (** Mat ** rix Operation, Swi ** ft **, was für Matft lol steht)

Der Anfang der Angelegenheit war ein Wort eines leitenden Angestellten des Unternehmens: "Ich möchte, dass Sie einen Code schreiben, um die inverse Matrix aus 3 Zeilen und 3 Spalten in Swift zu finden." Ich dachte, dass Swift eine N-dimensionale Matrixoperationsbibliothek wie Numpy in Python haben würde, aber als ich sie nachschlug, war es nicht überraschend. .. .. Das offizielle Beschleunigen scheint unpraktisch zu sein, und der berühmte Anstieg ist bis zu 2 Dimensionen? Es war wie. Aus diesem Grund habe ich beschlossen, meine eigene N-dimensionale Matrixoperationsbibliothek zu erstellen. (Es ist völlig überspezifiziert für den Code, der die inverse Matrix von 3 Zeilen und 3 Spalten findet, aber lol)

Darüber hinaus wurde Matft so erstellt. Und da es eine große Sache ist, werde ich es teilen und bin bis zur Gegenwart.

Überblick

Grundsätzlich wurde es nach Pythons Numpy erstellt, sodass die Funktionsnamen und die Verwendung fast mit Numpy identisch sind.

Erklärung

Die Deklaration erstellt ein mehrdimensionales Array mit "MfArray", nämlich "ndarray".

let a = MfArray([[[ -8,  -7,  -6,  -5],
                  [ -4,  -3,  -2,  -1]],
        
                 [[ 0,  1,  2,  3],
                  [ 4,  5,  6,  7]]])
print(a)
/*
mfarray = 
[[[	-8.0,		-7.0,		-6.0,		-5.0],
[	-4.0,		-3.0,		-2.0,		-1.0]],

[[	0.0,		1.0,		2.0,		3.0],
[	4.0,		5.0,		6.0,		7.0]]], type=Float, shape=[2, 2, 4]
*/

Schimmel

Ich wollte es mit verschiedenen Typen kompatibel machen, also habe ich einen bestimmten Typ vorbereitet. Es ist nicht "dtype", sondern "MfType".

let a = MfArray([[[ -8,  -7,  -6,  -5],
                  [ -4,  -3,  -2,  -1]],
            
                 [[ 0,  1,  2,  3],
                  [ 4,  5,  6,  7]]], mftype: .Float)
print(a)
/*
mfarray = 
[[[	-8.0,		-7.0,		-6.0,		-5.0],
[	-4.0,		-3.0,		-2.0,		-1.0]],

[[	0.0,		1.0,		2.0,		3.0],
[	4.0,		5.0,		6.0,		7.0]]], type=Float, shape=[2, 2, 4]
*/
let aa = MfArray([[[ -8,  -7,  -6,  -5],
                  [ -4,  -3,  -2,  -1]],
            
                 [[ 0,  1,  2,  3],
                  [ 4,  5,  6,  7]]], mftype: .UInt)
print(aa)
/*
mfarray = 
[[[	4294967288,		4294967289,		4294967290,		4294967291],
[	4294967292,		4294967293,		4294967294,		4294967295]],

[[	0,		1,		2,		3],
[	4,		5,		6,		7]]], type=UInt, shape=[2, 2, 4]
*/
//Above output is same as numpy!
/*
>>> np.arange(-8, 8, dtype=np.uint32).reshape(2,2,4)
array([[[4294967288, 4294967289, 4294967290, 4294967291],
        [4294967292, 4294967293, 4294967294, 4294967295]],

       [[         0,          1,          2,          3],
        [         4,          5,          6,          7]]], dtype=uint32)

Die Typliste wird durch den folgenden Aufzählungstyp definiert.

 public enum MfType: Int{
    case None // Unsupportted
    case Bool
    case UInt8
    case UInt16
    case UInt32
    case UInt64
    case UInt
    case Int8
    case Int16
    case Int32
    case Int64
    case Int
    case Float
    case Double
    case Object // Unsupported
}

Indexing Slices wie a [:, :: -1] in Numpy werden ebenfalls mit ~ < implementiert. (Ursprünglich wurde es mit ~ implementiert, aber ~ 2 usw. wird etwas gebissen. Nicht ... Es war dumm) Wir haben auch negative Indizes wie -1 implementiert. (Dies war vielleicht das Schwierigste ...)

let a = Matft.mfarray.arange(start: 0, to: 27, by: 1, shape: [3,3,3])
print(a)
/*
mfarray = 
[[[	0,		1,		2],
[	3,		4,		5],
[	6,		7,		8]],

[[	9,		10,		11],
[	12,		13,		14],
[	15,		16,		17]],

[[	18,		19,		20],
[	21,		22,		23],
[	24,		25,		26]]], type=Int, shape=[3, 3, 3]
*/
print(a[2,1,0])
// 21
print(a[1~<3]) //same as a[1:3] for numpy
/*
mfarray = 
[[[	9,		10,		11],
[	12,		13,		14],
[	15,		16,		17]],

[[	18,		19,		20],
[	21,		22,		23],
[	24,		25,		26]]], type=Int, shape=[2, 3, 3]
*/
print(a[-1~<-3])
/*
mfarray = 
	[], type=Int, shape=[0, 3, 3]
*/
print(a[~<~<-1]) // print(a[~<<-1])Mit einem Alias~<<Ist auch gleichwertig
/*
mfarray = 
[[[	18,		19,		20],
[	21,		22,		23],
[	24,		25,		26]],

[[	9,		10,		11],
[	12,		13,		14],
[	15,		16,		17]],

[[	0,		1,		2],
[	3,		4,		5],
[	6,		7,		8]]], type=Int, shape=[3, 3, 3]*/

Liste anderer Funktionen

Das Folgende ist eine Liste spezifischer Funktionen. Da die Hauptberechnung dem Beschleunigen überlassen bleibt, denke ich, dass die Berechnungszeit bis zu einem gewissen Grad garantiert ist.

\ * Bedeutet, dass diese Methode auch existiert. Mit anderen Worten, wenn "a" "MfArray" ist, können Sie "a.shallowcopy ()" verwenden.

Matft Numpy
*Matft.shallowcopy *numpy.copy
*Matft.deepcopy copy.deepcopy
Matft.nums numpy.ones * N
Matft.arange numpy.arange
Matft.eye numpy.eye
Matft.diag numpy.diag
Matft.vstack numpy.vstack
Matft.hstack numpy.hstack
Matft.concatenate numpy.concatenate
Matft Numpy
*Matft.astype *numpy.astype
*Matft.transpose *numpy.transpose
*Matft.expand_dims *numpy.expand_dims
*Matft.squeeze *numpy.squeeze
*Matft.broadcast_to *numpy.broadcast_to
*Matft.conv_order *numpy.ascontiguousarray
*Matft.flatten *numpy.flatten
*Matft.flip *numpy.flip
*Matft.clip *numpy.clip
*Matft.swapaxes *numpy.swapaxes
*Matft.moveaxis *numpy.moveaxis
*Matft.sort *numpy.sort
*Matft.argsort *numpy.argsort

--Dateibezogen Speichern ist unvollständig.

Matft Numpy
Matft.file.loadtxt numpy.loadtxt
Matft.file.genfromtxt numpy.genfromtxt

Die zweite Zeile ist der Operator.

Matft Numpy
Matft.add
+
numpy.add
+
Matft.sub
-
numpy.sub
-
Matft.div
/
numpy.div
.
Matft.mul
*
numpy.multiply
*
Matft.inner
*+
numpy.inner
n/a
Matft.cross
*^
numpy.cross
n/a
Matft.matmul
*&
numpy.matmul
@
Matft.equal
===
numpy.equal
==
Matft.not_equal
!==
numpy.not_equal
!=
Matft.allEqual
==
numpy.array_equal
n/a
Matft.neg
-
numpy.negative
-
Matft Numpy
Matft.math.sin numpy.sin
Matft.math.asin numpy.asin
Matft.math.sinh numpy.sinh
Matft.math.asinh numpy.asinh
Matft.math.sin numpy.cos
Matft.math.acos numpy.acos
Matft.math.cosh numpy.cosh
Matft.math.acosh numpy.acosh
Matft.math.tan numpy.tan
Matft.math.atan numpy.atan
Matft.math.tanh numpy.tanh
Matft.math.atanh numpy.atanh

Da es problematisch ist, werde ich es weglassen. .. .. Lol Siehe hier

Matft Numpy
*Matft.stats.mean *numpy.mean
*Matft.stats.max *numpy.max
*Matft.stats.argmax *numpy.argmax
*Matft.stats.min *numpy.min
*Matft.stats.argmin *numpy.argmin
*Matft.stats.sum *numpy.sum
Matft.stats.maximum numpy.maximum
Matft.stats.minimum numpy.minimum
Matft Numpy
Matft.linalg.solve numpy.linalg.solve
Matft.linalg.inv numpy.linalg.inv
Matft.linalg.det numpy.linalg.det
Matft.linalg.eigen numpy.linalg.eig
Matft.linalg.svd numpy.linalg.svd
Matft.linalg.polar_left scipy.linalg.polar
Matft.linalg.polar_right scipy.linalg.polar
Matft.linalg.normlp_vec scipy.linalg.norm
Matft.linalg.normfro_mat scipy.linalg.norm
Matft.linalg.normnuc_mat scipy.linalg.norm

Installation

Unterstützung für SwiftPM, CocoaPod und Carthage hinzugefügt.

SwiftPM

CocoaPods

  pod init
  target 'your project' do
    pod 'Matft'
  end

--Installation

  pod install

Karthago (unbestätigt)

-Erstellen Sie in Cartfile und lesen Sie.

echo 'github "realm/realm-cocoa"' > Cartfile
carthage update ###or append '--platform ios'

――Es ist in Ordnung, wenn Sie das fertige Matft.framework in das Projekt laden.

Performance

Ich sagte, dass die Berechnung garantiert ist, weil ich es dem Beschleunigen überlasse, aber ich habe die Geschwindigkeit nur durch Hinzufügen berechnet. Wenn ich Zeit habe, werde ich andere Funktionen untersuchen. .. ..

case Matft Numpy
1 1.14ms 962 µs
2 4.20ms 5.68 ms
3 4.17ms 3.92 ms
func testPefAdd1() {
        do{
            let a = Matft.mfarray.arange(start: 0, to: 10*10*10*10*10*10, by: 1, shape: [10,10,10,10,10,10])
            let b = Matft.mfarray.arange(start: 0, to: -10*10*10*10*10*10, by: -1, shape: [10,10,10,10,10,10])
            
            self.measure {
                let _ = a+b
            }
            /*
             '-[MatftTests.ArithmeticPefTests testPefAdd1]' measured [Time, seconds] average: 0.001, relative standard deviation: 23.418%, values: [0.001707, 0.001141, 0.000999, 0.000969, 0.001029, 0.000979, 0.001031, 0.000986, 0.000963, 0.001631]
            1.14ms
             */
        }
    }
    
    func testPefAdd2(){
        do{
            let a = Matft.arange(start: 0, to: 10*10*10*10*10*10, by: 1, shape: [10,10,10,10,10,10])
            let b = a.transpose(axes: [0,3,4,2,1,5])
            let c = a.T
            
            self.measure {
                let _ = b+c
            }
            /*
             '-[MatftTests.ArithmeticPefTests testPefAdd2]' measured [Time, seconds] average: 0.004, relative standard deviation: 5.842%, values: [0.004680, 0.003993, 0.004159, 0.004564, 0.003955, 0.004200, 0.003998, 0.004317, 0.003919, 0.004248]
            4.20ms
             */
        }
    }

    func testPefAdd3(){
        do{
            let a = Matft.arange(start: 0, to: 10*10*10*10*10*10, by: 1, shape: [10,10,10,10,10,10])
            let b = a.transpose(axes: [1,2,3,4,5,0])
            let c = a.T
            
            self.measure {
                let _ = b+c
            }
            /*
             '-[MatftTests.ArithmeticPefTests testPefAdd3]' measured [Time, seconds] average: 0.004, relative standard deviation: 16.815%, values: [0.004906, 0.003785, 0.003702, 0.005981, 0.004261, 0.003665, 0.004083, 0.003654, 0.003836, 0.003874]
            4.17ms
             */
        }
}
In [1]:
import numpy as np
#import timeit

a = np.arange(10**6).reshape((10,10,10,10,10,10))
b = np.arange(0, -10**6, -1).reshape((10,10,10,10,10,10))

#timeit.timeit("b+c", repeat=10, globals=globals())
%timeit -n 10 a+b
962 µs ± 273 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [2]:
a = np.arange(10**6).reshape((10,10,10,10,10,10))
b = a.transpose((0,3,4,2,1,5))
c = a.T
#timeit.timeit("b+c", repeat=10, globals=globals())
%timeit -n 10 b+c
5.68 ms ± 1.45 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [3]:
a = np.arange(10**6).reshape((10,10,10,10,10,10))
b = a.transpose((1,2,3,4,5,0))
c = a.T
#timeit.timeit("b+c", repeat=10, globals=globals())
%timeit -n 10 b+c
3.92 ms ± 897 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

Was ich persönlich mag

Feinheiten

Schließlich

Ich habe es aus einer Laune heraus geschafft, aber ich habe etwas Besseres bekommen, als ich erwartet hatte. Es gibt vielleicht eine bessere Bibliothek, nur weil mir die Suchkraft fehlt, aber ich wäre Ihnen dankbar, wenn Sie es versuchen könnten. (Die umweltabhängige Prüfung wurde noch nicht abgeschlossen. Bitte zögern Sie nicht, uns zu kontaktieren ...) Wie auch immer, es war eine gute Studie. Vielen Dank.

Referenz

numpy scipy Accelerate Schreiben Sie NDArray in Swift (Ich habe auf den Testfall verwiesen.)

Recommended Posts

Ich habe mit Swift eine N-dimensionale Matrixoperationsbibliothek Matft erstellt
Ich habe einen Ansible-Installer gemacht
Ich habe versucht, eine ganzzahlige Matrix mit Numpy zu standardisieren
Ich habe einen Blackjack mit Python gemacht!
Versuchen Sie die Matrixoperation mit NumPy
Ich habe einen Xubuntu-Server erstellt.
Ich habe eine Animation gemacht, die Othellos Stein mit POV-Ray zurückgibt
Ich habe COVID19_simulator mit JupyterLab erstellt
Ich habe Word2Vec mit Pytorch gemacht
Ich habe mit Python einen Blackjack gemacht.
Ich habe Wordcloud mit Python gemacht.
Ich habe eine Bibliothek erstellt, die Konfigurationsdateien mit Python einfach lesen kann
Ich möchte eine externe Bibliothek mit IBM Cloud-Funktionen verwenden
[Python] Ich habe einen Bildbetrachter mit einer einfachen Sortierfunktion erstellt.
Ich habe einen Anpanman-Maler diskriminiert
Ich habe meine eigene Python-Bibliothek erstellt
Ich habe mit Python eine Lotterie gemacht.
Ich habe eine SMS mit Python gesendet
Ich habe ein Angular Starter Kit gemacht
Ich habe mit Python einen Daemon erstellt
Ich habe den APL-Teil mit der Alexa-Fertigkeit "Industry Term Conversion" erstellt.
Ich erhalte eine Fehlermeldung beim Import von Pandas.
Ich habe versucht, eine SMS mit Twilio zu senden
Ich habe mit Python einen Zeichenzähler erstellt
Ich habe eine Online-Frequenzanalyse-App erstellt
Ich habe ein alternatives Modul für japandas.DataReader erstellt
Ich habe mit Python eine Hex-Map erstellt
Ich habe ein Lebensspiel mit Numpy gemacht
Ich habe einen Hanko-Generator mit GAN gemacht
Ich habe mit Python ein schurkenhaftes Spiel gemacht
Ich habe mit Python einen einfachen Blackjack gemacht
Ich habe mit Python eine Einstellungsdatei erstellt
Ich habe eine Bibliothek für versicherungsmathematische Versicherungen erstellt
Ich habe eine WEB-Bewerbung bei Django gemacht
Ich habe mit Python einen Neuronensimulator erstellt
Mit LINEBot habe ich eine Anwendung erstellt, die mich über die "Buszeit" informiert.
Ich habe mit Yocto ein Bild für Qemu gemacht, aber ich habe versagt und von vorne angefangen