anchor.diff:  
   let isStemmedMatch input word =
       let word' = stem word |> Regex.Escape // TODO strip punctuation?
  -    Regex.IsMatch(input, sprintf @"\b%s" word', RegexOptions.IgnoreCase)
  +    Regex.IsMatch(stemWords input, sprintf @"\b%s" word', RegexOptions.IgnoreCase)
   let stemmedWordMatch = features isStemmedMatch
   
   let stringContainsMatch = features containedIn
   
  +printfn "Extracting training features..."
   let trainInput = 
       train.Rows
  -    |> Seq.map (fun w ->
  +    |> PSeq.ordered
  +    |> PSeq.map (fun w ->
           stemmedWordMatch
             w.Search_term
             w.Product_title
             (productDescription w.Product_uid)
             (attribs w.Product_uid)
             (brandName w.Product_uid))
  -    |> Seq.toArray
  +    |> PSeq.toArray
   
   let trainOutput = 
       train.Rows
       |> Seq.map (fun t -> float t.Relevance)
       |> Seq.toArray
   
  +printfn "Regressing..."
   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.48917 - stem all words for comparison
   //0.48940 - added title & desc length feature
   //0.49059 - added desc word match ratio
   //0.49080 - added title word match ratio
  
positive.code: type Attributes = CsvProvider<"../data/attributes.csv">
  let attributes = Attributes.GetSample()
  
  let productDescMap =
      products.Rows
      |> Seq.map (fun pd -> pd.Product_uid, pd.Product_description)
      |> Map.ofSeq
  let inline productDescription uid = productDescMap |> Map.find uid
  
  let attribMap =
      attributes.Rows
      |> Seq.map (fun r -> r.Product_uid, r.Name, r.Value)
      |> Seq.groupBy (fun (i,_,_) -> i)
      |> Map.ofSeq
  
  let brands =
    attributes.Rows
    |> Seq.where (fun r -> r.Name = "MFG Brand Name")
  
negative.code: //0.50783 - kaggle reported from stemmed
  //0.5063 - string contains
  
  printfn "Extracting testing features..."
  let testInput = 
      test.Rows
      |> PSeq.ordered
      |> PSeq.map (fun w ->
          stemmedWordMatch
            w.Search_term
            w.Product_title
            (productDescription w.Product_uid)
            (attribs w.Product_uid)
            (brandName w.Product_uid))
      |> PSeq.toArray
  
  printfn "Predicting..."
  let testOutput = target.Compute(testInput)
  let inline bracket n = Math.Max(1., Math.Min(3., n))
  let testOutput' = testOutput |> Seq.map bracket
  
  printfn "Writing results..."
  let submission = 
      Seq.zip test.Rows testOutput
      |> PSeq.ordered
      |> PSeq.map (fun (r,o) -> sprintf "%A,%A" r.Id o)
      |> PSeq.toList
  let outputPath = __SOURCE_DIRECTORY__ + @"../../data/benchmark_submission_FSharp.csv"
  File.WriteAllLines(outputPath, "id,relevance" :: submission)
  