anchor.diff:          result.[0])
     predict
   
  -let rfQuality = evaluate rfLearn
  +//let rfQuality = evaluate rfLearn
   submission rfLearn
   //0.48737 = kaggle rsme; oobrmserror = 0.4776784128; rmserror = 0.4303968628
   //? = kaggle rsme; oobrmserror = 0.4147019175; rmserror = 0.3529753185
  
positive.code:     attribs
      |> Seq.where (fun a -> not <| String.IsNullOrWhiteSpace a)
      |> Seq.fold
          (fun (state:StringBuilder) t -> state.Replace(t, ""))
          (StringBuilder(desc))
      |> string
  
  let features attrSelector productBrand (sample:CsvData.Sample) =
      let words = sample.Query
      let title = sample.Title
      let attributes = attrSelector sample.ProductId
      let desc = sample.Description |> fixLineConcats attributes
      let deduped = attributes |> Seq.where (fun a -> a |> containedIn desc |> not) |> String.concat " "
  //    printfn "%d pre %d post" (Seq.length attributes) (Seq.length deduped)
      let uniqueWords = words |> splitOnSpaces |> Array.distinct
      let titleMatches = uniqueWords |> Array.filter (isMatch title) |> Array.distinct
      let descMatches = uniqueWords |> Array.filter (isMatch desc) |> Array.distinct
      let attrMatches = uniqueWords |> Array.filter (isMatch deduped) |> Array.distinct
      let wordMatchCount =
          uniqueWords
          |> Seq.filter (fun w -> Seq.concat [titleMatches; descMatches; attrMatches] |> Seq.contains w)
  
negative.code:        float descMatches.Length
         float descMatches.Length / float uniqueWords.Length
         float attrMatches.Length
         queryTitlePosScore
  //       float attrMatches.Length / float uniqueWords.Length
         float brandNameMatch |]
  
  