anchor.diff:      |> PSeq.map (fun w -> wordMatch w.Search_term w.Product_title (productDescription w.Product_uid) |> toFloatArray)
       |> PSeq.toArray
   
  -let target = MultipleLinearRegression(3, true);
  -let error = target.Regress(trainInput, trainOutput);
  +let target = MultipleLinearRegression(3, true)
  +let error = target.Regress(trainInput, trainOutput)
   let testOutput = target.Compute(testInput)
   
   let submission = 
       Seq.zip test.Rows testOutput
  -    |> PSeq.map (fun (r,o) -> sprintf "%A,%A" r.Id o)
  -    |> PSeq.toArray
  -
  +    |> Seq.map (fun (r,o) -> sprintf "%A,%A" r.Id o)
  +    |> Seq.toList
   let outputPath = __SOURCE_DIRECTORY__ + @"../../data/benchmark_submission_FSharp.csv"
  -File.WriteAllLines(outputPath, submission)
  +File.WriteAllLines(outputPath, "id,relevance" :: submission)
  
positive.code:     |> Map.ofSeq
  let inline productDescription uid = productDescMap |> Map.find uid
  
  (* wordMatch needs to have a fuzzy match
     The sample R script uses a regex like this:
     pattern <- paste("(^| )",words[i],"($| )",sep="") *)
  let wordMatch (words:string) (title:string) (desc:string) =
      let isMatch input word = // TODO should stem words, e.g. "angles" -> "angle"
          Regex.IsMatch(input, sprintf @"\b%s\b" (Regex.Escape word), RegexOptions.IgnoreCase)
      let words' = words.Split([|' '|], StringSplitOptions.RemoveEmptyEntries)
      let uniqueWords = words' |> Array.distinct
      let numberInTitle = uniqueWords |> Array.filter (isMatch title) |> Array.length
      let numberInDescription = uniqueWords |> Array.filter (isMatch desc) |> Array.length
      numberInTitle, numberInDescription, uniqueWords.Length 
  
negative.code: open FSharp.Data
  open FSharp.Collections.ParallelSeq
  open Accord.Statistics.Models.Regression.Linear
  open Iveonik.Stemmers
  
  [<Literal>]
  let trainDataPath = "../data/train.csv"
  