2017-07-19 8 views
2

は、私は2つのリストを取る内積関数を記述:ドット製品機能

let inline dot a b = 
    List.zip a b 
    |> List.map (fun (a, b) -> a * b) 
    |> List.reduce (+) 

List.zipを使用せずに、ドット積を計算するための良い方法はありますか?

答えて

6

一つの短い方の方法は、List.map2を使用することです:

let inline dot a b = List.map2 (*) a b |> List.sum 

List.fold2を使用することです:

let inline dot a b = List.fold2 (fun state x y -> state + x * y) LanguagePrimitives.GenericZero a b 
+0

2番目の関数の 'inline'は' 0'が 'int '型の戻り値を持つようにしているので役に立ちません。 – Soldalma

+0

'inline'が関数を一般化可能にする場合、' 0'の代わりに 'LanguagePrimitives.GenericZero'を使うと動作します。コンパイラに "ここで関数呼び出しを生成しない"と伝えるのであれば、それはそのままです。 – rmunn

3

私はマトリクスでのF#でニューラルネットワークを行うための同じ必要性を持っていましたが、あなたおそらくベクトルを使用する可能性があります。

私はMathNet Numericsを使用しました。これには他の多くの機能があります。dot productです。

coreF# extensionsの両方を取得してください。

あなたはニューラルネットワークをやっていると行列とのMathNetニューメリックスを使用する場合は、あなたはおそらくここSigmoid function

MathNet Raise Scalar by a Matrix

は、F#でMathNetニューメリックマトリックスを用いたニューラルネットワークに関連したバックプロパゲーションexampleあるでしょう。私はList.fold2を使用して1が最速であると信じて3提案したものの中で

3

、:

let inline dot1 a b = 
    List.zip a b 
    |> List.map (fun (a, b) -> a * b) 
    |> List.reduce (+) 

let inline dot2 a b = List.map2 (*) a b |> List.sum 

// Modified with 0.0 instead of 0 and no 'inline' 
let dot3 a b = List.fold2 (fun state x y -> state + x * y) 0.0 a b 

let xs = [0.0..1000000.0] 

> dot1 xs xs;; 
Real: 00:00:00.242, 

> dot2 xs xs;; 
Real: 00:00:00.070 

> dot3 xs xs;; 
Real: 00:00:00.003 

二つのリストをお越しは、おそらく非常に高価です。 map2-sumソリューションは高速ですが、リストを2回反復します。 fold2ソリューションはリストを1回だけ通過します。

+0

'dot3'をジェネリック関数にするために' LanguagePrimitives.GenericZero'ではなく '0.0'を使ったのはなぜですか?私はジェネリック医薬品が機能をより速く評価できるようにすることを強く求めないのですか? – MiP

+0

@MiP - わかりません。私は '0.0 'の代わりに' LanguagePrimitives.GenericZero'を使ってやり直してみましたが、速度はかなり変わっていませんでした。 – Soldalma

関連する問題