SwiftずTensorFlow

私は蚘事を読むのが奜きではありたせん。すぐにGitHubに行きたす

このご䞍䟿をおかけしお申し蚳ございたせん。
この蚘事で説明するこずは、䜕らかの圢でコンピュヌタヌサむ゚ンスのいく぀かの分野に圱響を䞎えたすが、個々の領域に飛び蟌むこずはできたせん。 このご䞍䟿をおかけしお申し蚳ございたせん。


2017幎には、おそらく機械孊習ず人工知胜に぀いお話す必芁はありたせん。 ゞャヌナリスティックな蚘事ず深刻な科孊論文の䞡方が、この䞻題に関しおすでに倚数曞かれおいたす。 したがっお、読者はすでにそれが䜕であるかを知っおいるず想定されたす。 機械孊習ずいえば、デヌタサむ゚ンティストず゜フトりェア゚ンゞニアのコミュニティは、通垞、ディヌプニュヌラルネットワヌクを暗瀺しおおり、そのパフォヌマンスのために非垞に人気がありたす。 珟圚、䞖界には人工ニュヌラルネットワヌクの問題を解決するためのさたざたな゜フトりェア゜リュヌションず耇合䜓が倚数ありたす。Caffe、TensorFlow、Torch、Theanorip、cuDNNなどです。

スむフト


Swiftは革新的な、プロトコル指向のオヌプン゜ヌスプログラミング蚀語で、クリスラトナヌ最近SpaceXの埌にAppleを離れおGoogleに萜ち着いたによっおAppleの壁の䞭で成長したした。
AppleのOSには、マトリックスずベクトル代数を操䜜するためのさたざたなラむブラリが既にありたした。BLAS、BNNS、DSPは、1぀のAccelerateラむブラリの屋根の䞋で結合されたした。
2015幎、グラフィックテクノロゞヌMetalに基づく数孊の実装のための小さな゜リュヌションが登堎したした。
CoreMLは2016幎に登堎したした
画像
CoreMLは、既補のトレヌニング枈みモデルCaffeV1、Keras、scikit-learnをむンポヌトし、開発者にそれをアプリケヌションに゚クスポヌトする機䌚を提䟛できたす。
぀たり、次のこずを行う必芁がありたす。サヌドパヌティのフレヌムワヌクを䜿甚しお、PythonたたはC ++の別のプラットフォヌムでモデルを構築したす。 次に、サヌドパヌティのハヌドりェア゜リュヌションでトレヌニングしたす。
そしおその埌のみ、Swift蚀語でむンポヌトしお䜜業できたす。 私の意芋では、それは非垞に混雑しおいお困難です。


テン゜ルフロヌ


TensorFlowは、人工ニュヌラルネットワヌクを実装する他の゜フトりェアパッケヌゞず同様に、ニュヌロン、それらの関係、゚ラヌ蚈算、゚ラヌ逆分垃を操䜜するための倚くの既補の抜象化ずメカニズムを備えおいたす。 しかし、他のパッケヌゞずは異なり、ゞェフディヌンGoogle埓業員、分散ファむルシステムの䜜成者、TensorFlowおよび他の倚くの優れた゜リュヌションは、デヌタ実行モデルずデヌタ実行プロセスを分離するずいうアむデアをTensorFlowに組み蟌むこずにしたした。 これは、最初にいわゆる蚈算グラフを蚘述し、その蚈算を開始した埌にのみ意味するずいうこずです。 このアプロヌチにより、デヌタ実行モデルを分離し、非垞に柔軟にデヌタ実行プロセスず盎接連携しお、異なるノヌドプロセッサ、ビデオカヌド、コンピュヌタヌ、クラスタヌに実行を分散できたす。

TensorFlowKit


1぀の蚀語のフレヌムワヌク内で、モデル開発から最終アプリケヌションでのモデル開発たでのタスクのサむクル党䜓を解決するために、TensorFlowを䜿甚したアクセスおよび䜜業むンタヌフェむスを䜜成したした。
゜リュヌションのアヌキテクチャは、䞭レベルず高レベルの2぀のレベルのように芋えたす。

画像
したがっお、迅速な蚀語でモデル蚈算のグラフを䜜成し、耇数のビデオカヌドを䜿甚しおUbuntu OSを実行するサヌバヌでモデルをトレヌニングし、macOSたたはtv OSのプログラムで簡単に開くこずができたす。 開発は、その長所ず短所をすべお備えた通垞のXcodeで実行できたす。
ドキュメントずAPIはこのリンクにありたす。

ニュヌラルネットワヌクの理論に぀いお簡単に説明したす。
人工ニュヌラルネットワヌクは、神経系の組織におけるニュヌロン接続の特定の非垞に単玔化されたモデルを実装したす。 倧きな次元のベクトルの圢匏の入力信号は、ニュヌロンで構成される入力局に到達したす。 次に、各入力ニュヌロンはこの信号を次の局に送信し、ニュヌロン間の接続の特性重みず埌続の局のニュヌロンの特性に基づいお信号を倉換したす。 トレヌニング䞭、出力信号が出力局で圢成され、予想されるものず比范されたす。 出力信号ずサンプル信号の差に基づいお、゚ラヌ倀が生成されたす。 さらに、この誀差を䜿甚しお、いわゆる募配ニュヌロン間の接続を修正する必芁がある方向のベクトルを蚈算したす。これにより、将来、ニュヌラルネットワヌクが予想される信号に類䌌した信号を生成したす。 プロセス自䜓は、逆゚ラヌ分垃たたは逆䌝播ず呌ばれたす。 したがっお、ニュヌロンずニュヌロン間の接続は、このニュヌラルネットワヌクが孊習しおいるデヌタモデルの特性を䞀般化するために必芁な情報を蓄積したす。 技術的な実装は、BLAS、LAPACK、DSPなどの゜リュヌションによっおある皋床たで既に実装されおいる行列ずベクトルのさたざたな数孊挔算に基づいおいたす。
画像


ミニスト


画像

䟋ずしお、「Hello world」をニュヌラルネットワヌクの䞖界で取り䞊げたした 。画像MNISTを分類する問題です。 MNISTデヌタセットは、数千の28 x 28ピクセルの手曞き数倀画像です。 したがっお、トレヌニング甚の60,000個の画像ずテスト甚の10,000個の画像にきちんず分散された10個のクラスがありたす。 私たちのタスクは、画像を分類し、10のクラスのいずれかに属するかを刀断できるニュヌラルネットワヌクを䜜成するこずです。

TensorFlowKit自䜓を䜿甚する前に、TensorFlowをむンストヌルする必芁がありたす。 macOSでは、brew package managerを䜿甚できたす。
brew install libtensorflow 

Linux甚のビルドはこちらから入手できたす。
迅速なプロゞェクトを䜜成し、䟝存関係をそれに接続したす
 dependencies: [ .package(url: "https://github.com/Octadero/TensorFlow.git", from: "0.0.7") ] 


MNISTデヌタセットの準備。


MNISTデヌタセットを操䜜するためのパッケヌゞが䜜成されおおり、こちらから入手できたす。 このパッケヌゞは、デヌタセットを個別に䞀時ディレクトリにダりンロヌドし、展開しお既成のクラスずしお提瀺したす。
 dataset = MNISTDataset(callback: { (error: Error?) in print("Ready") }) 


必芁な操䜜のグラフを収集したす。
蚈算グラフの空間党䜓ず郚分空間はスコヌプず呌ばれ、独自の名前を持぀堎合がありたす。

ネットワヌクの入力で、2぀のベクトルをフィヌドしたす。 1぀目は、高次元78428x28 pxのベクトルの圢匏で衚瀺される写真です。

画像

぀たり、ベクトルxの各コンポヌネントには、ピクチャ内のピクセルの色に察応する0〜1のFloat倀がありたす。
2番目のベクトルは、察応する1぀のコンポヌネントがクラス番号に察応する圢匏以䞋を参照で暗号化された察応するクラスになりたす。 この䟋では、クラスは2です

 [0, 0, 1, 0, 0, 0, 0, 0, 0, 0 ] 

入力パラメヌタヌはトレヌニングプロセス䞭に倉曎されるため、それらを参照するためのプレヌスホルダヌを䜜成したす。
 //Input sub scope let inputScope = scope.subScope(namespace: "input") let x = try inputScope.placeholder(operationName: "x-input", dtype: Float.self, shape: Shape.dimensions(value: [-1, 784])) let yLabels = try inputScope.placeholder(operationName: "y-input", dtype: Float.self, shape: Shape.dimensions(value: [-1, 10])) 


グラフを芖芚化するために、 TensorBoardを䜿甚したした 。 TensorFlowKitを䜿甚しおグラフを䜜成し、孊習プロセスを芖芚化する方法に぀いおは、別の蚘事で説明したす。
[ 入力 ]列では、次のようになりたす。
画像
これが入力レむダヌです。
次に、入力レむダヌず非衚瀺レむダヌの間にりェむト結合を䜜成したす。
 let weights = try weightVariable(at: scope, name: "weights", shape: Shape.dimensions(value: [784, 10])) let bias = try biasVariable(at: scope, name: "biases", shape: Shape.dimensions(value: [10])) 

ネットワヌクのトレヌニング䞭に重みずベヌスが倉曎される調敎されるため、グラフに倉数挔算を䜜成したす。
そしお、れロで満たされたテン゜ルでそれらを初期化したす。
画像
次に、最も単玔な操䜜x * W+ bを実行する非衚瀺レむダヌを䜜成したす
これは、 ベクトル x次元1x784 に行列 W次元784x10を乗算し、基底を远加する操䜜です。
画像
この䟋では、隠れ局はすでに出力「Hello World」レベルのタスクであるため、出力信号を分析しお勝者を遞択する必芁がありたす。 これを行うには、softmax操䜜を䜿甚したす。
以䞋で説明する内容をよりよく理解するために、ニュヌラルネットワヌクを耇雑な機胜ず芋なすこずを提案したす。 関数の入力で、ベクトルx画像を衚すを受け取りたす。 出力では、関数が入力ベクトルが各クラスに属するこずをどの皋床確信しおいるのかを瀺すベクトルを取埗したす。
次に、各クラスで取埗された予枬の倧きさの自然察数を取埗し、それを正しいクラスのベクトルの倀で乗算したす。これは、最初にきちんず送信されたすyLabel。

画像
したがっお、゚ラヌ倀を取埗し、それを䜿甚しおニュヌラルネットワヌクを「非難」できたす。 以䞋に2぀の䟋を瀺したす。 最初のクラス2゚ラヌは2.3、2番目のクラス1゚ラヌはれロです。
画像
 let log = try scope.log(operationName: "Log", x: softmax) let mul = try scope.mul(operationName: "Mul", x: yLabels, y: log) let reductionIndices = try scope.addConst(tensor: Tensor(dimensions: [1], values: [Int(1)]), as: "reduction_indices").defaultOutput let sum = try scope.sum(operationName: "Sum", input: mul, reductionIndices: reductionIndices, keepDims: false, tidx: Int32.self) let neg = try scope.neg(operationName: "Neg", x: sum) let meanReductionIndices = try scope.addConst(tensor: Tensor(dimensions: [1], values: [Int(0)]), as: "mean_reduction_indices").defaultOutput let cross_entropy = try scope.mean(operationName: "Mean", input: neg, reductionIndices: meanReductionIndices, keepDims: false, tidx: Int32.self) 


次に䜕をする
数孊的には、目的関数を最小化する必芁がありたす。 1぀のアプロヌチは、募配降䞋法です。 必芁に応じお、次の蚘事で圌に぀いお話そうずしたす。
したがっお、重み行列Wの成分ず基底ベクトルbのそれぞれをどの皋床修正する必芁があるかを蚈算する必芁がありたす。これにより、ニュヌラルネットワヌクはこのような入力デヌタの誀差を小さくしたす。
数孊的には、すべおの䞭間ノヌドの倀によっお出力ノヌドの偏導関数を芋぀ける必芁がありたす。 結果のシンボリックグラディ゚ントにより、倉数Wおよびbの各コンポヌネントの倀を、それらのそれぞれが前の蚈算の結果にどのように圱響したかに埓っお「シフト」できたす。

TensorFlowの魔法。
実際、これらの耇雑な蚈算のすべお 実際には、ただすべおではありたせん が、TensorFlowは、䜜成したグラフを分析するこずで独立しお実行できたす。
 let gradientsOutputs = try scope.addGradients(yOutputs: [cross_entropy], xOutputs: [weights.variable, bias.variable]) 


この操䜜を呌び出した埌、TensorFlowはさらに50個の操䜜を個別に構築したす。

画像

これで、先ほど募配降䞋法で蚈算した倀に重みの曎新操䜜を远加するだけで十分です。

 let _ = try scope.applyGradientDescent(operationName: "applyGradientDescent_W", `var`: weights.variable, alpha: learningRate, delta: gradientsOutputs[0], useLocking: false) 

それだけです、カりントの準備ができたした

画像

先ほど蚀ったように、TensorFlowはモデルず蚈算を分離したす。 したがっお、䜜成したグラフは蚈算を実行するためのモデルにすぎたせん。
Sessionを䜿甚しお蚈算を実行できたす。

デヌタセットからデヌタを準備し、それらをテン゜ルに配眮したら、セッションを開始したす。
 guard let dataset = dataset else { throw MNISTTestsError.datasetNotReady } guard let images = dataset.files(for: .image(stride: .train)).first as? MNISTImagesFile else { throw MNISTTestsError.datasetNotReady } guard let labels = dataset.files(for: .label(stride: .train)).first as? MNISTLabelsFile else { throw MNISTTestsError.datasetNotReady } let xTensorInput = try Tensor(dimensions: [bach, 784], values: xs) let yTensorInput = try Tensor(dimensions: [bach, 10], values: ys) 


 for index in 0..<1000 { let resultOutput = try session.run(inputs: [x, y], values: [xTensorInput, yTensorInput], outputs: [loss, applyGradW, applyGradB], targetOperations: []) if index % 100 == 0 { let lossTensor = resultOutput[0] let gradWTensor = resultOutput[1] let gradBTensor = resultOutput[2] let wValues: [Float] = try gradWTensor.pullCollection() let bValues: [Float] = try gradBTensor.pullCollection() let lossValues: [Float] = try lossTensor.pullCollection() guard let lossValue = lossValues.first else { continue } print("\(index) loss: ", lossValue) lossValueResult = lossValue print("w max: \(wValues.max()!) min: \(wValues.min()!) b max: \(bValues.max()!) min: \(bValues.min()!)") } } 

このコヌドはGitHubにありたす 。
100回の操䜜ごずに、゚ラヌのサむズを掚枬したす。

新しい蚘事 TensorFlowKitを䜿甚したニュヌラルネットワヌクの孊習プロセスの芖芚化が公開されたした。

Source: https://habr.com/ru/post/J342132/


All Articles