anchor.diff:  open Accord.Statistics.Models.Regression.Linear
   open Iveonik.Stemmers
   open FSharp.Collections.ParallelSeq
  +open System.Collections.Concurrent
   
   type Train = CsvProvider<"../data/train.csv">
   let train = Train.GetSample()
  
positive.code: 
  let isStemmedMatch input word =
      let word' = stem word |> Regex.Escape // TODO strip punctuation?
      Regex.IsMatch(input, sprintf @"\b%s" word', RegexOptions.IgnoreCase)
  let stemmedWordMatch = features isStemmedMatch
  
  let stringContainsMatch = features containedIn
  
  let trainInput = 
      train.Rows
      |> Seq.map (fun w ->
          stemmedWordMatch
            w.Search_term
            w.Product_title
            (productDescription w.Product_uid)
            (attribs w.Product_uid)
            (brandName w.Product_uid))
      |> Seq.toArray
  
  let trainOutput = 
      train.Rows
      |> Seq.map (fun t -> float t.Relevance)
      |> Seq.toArray
  
  let target = MultipleLinearRegression(11, true)
  let sumOfSquaredErrors = target.Regress(trainInput, trainOutput)
  let observationCount = trainInput |> Seq.length |> float
  let sme = sumOfSquaredErrors / observationCount
  let rsme = sqrt(sme)
  //0.48940 - added title & desc length feature
  //0.49059 - added desc word match ratio
  //0.49080 - added title word match ratio
  
negative.code:       brand |> Option.map (fun (_, _, value) -> value)
      | None -> None
  
  let stemDict = ConcurrentDictionary<string,string>(StringComparer.OrdinalIgnoreCase)
  let stem word = stemDict.GetOrAdd(word, (fun s -> (new EnglishStemmer()).Stem s))
  let splitOnSpaces (str:string) = str.Split([|' '|], StringSplitOptions.RemoveEmptyEntries)
  let stemWords = splitOnSpaces >> Array.map stem >> String.concat " "
  
  let containedIn (input:string) word =
      input.IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0
  
  let features isMatch (words:string) title desc attribs productBrand =
      let uniqueWords = words |> splitOnSpaces |> Array.distinct
      let titleMatches = uniqueWords |> Array.filter (isMatch title)
      let descMatches = uniqueWords |> Array.filter (isMatch desc)
      let attrMatches = uniqueWords |> Array.filter (isMatch attribs)
  