Skip to content

Instantly share code, notes, and snippets.

@sudipto80
Created June 15, 2015 06:59
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sudipto80/72e6e56d07110baf4d4d to your computer and use it in GitHub Desktop.
Save sudipto80/72e6e56d07110baf4d4d to your computer and use it in GitHub Desktop.
Kaggle Challenge (Handwritten Digit Recognizer)
// Learn more about F# at http://fsharp.net
// See the 'F# Tutorial' project for more help.
open System.IO
open System
open System.Windows.Forms
open System.Drawing
type Entry = {Label :string; Values : int list}
let updateStatus (form:Form , text:string) =
let graphics = form.CreateGraphics()
let point = new PointF((float32)5, (float32)5)
let font = new Font(family = FontFamily.GenericSansSerif, emSize = (float32)30)
graphics.DrawString(text, font, new SolidBrush(Color.YellowGreen), point)
//Draws the digit
let drawDigit (pixels:float[], label:string) =
let tile = 20
let form = new Form(TopMost = true, Visible = true, Width = 29 * tile, Height = 29 * tile)
let panel = new Panel(Dock = DockStyle.Fill)
panel.BackColor <- Color.Black
form.Controls.Add(panel)
let graphics = panel.CreateGraphics()
pixels
|> Array.iteri (fun i p ->
let col = i % 28
let row = i / 28
let color = Color.FromArgb(int p, int p, int p)
let brush = new SolidBrush(color)
graphics.FillRectangle(brush,col*tile,row*tile,tile,tile))
let point = new PointF((float32)5, (float32)5)
let font = new Font(family = FontFamily.GenericSansSerif, emSize = (float32)30)
graphics.DrawString(label, font, new SolidBrush(Color.YellowGreen), point)
form.Show()
//Euclidean distance
let distance ( values1 : int list , values2 : int list) =
values1
|> List.zip values2
|> List.map ( fun it -> Math.Pow( float (fst it) - float (snd it),2.0))
|> List.sum
//Loading values from the training/test data.
//This assumes that the first one is the label/class/category of the data
let loadValues (filename : string) =
File.ReadAllLines(filename)
|> Seq.ofArray
|> Seq.skip (1) // leave the first row as that's the column
|> Seq.map ( fun line -> { Label = line.Substring(0,line.IndexOf(','));
Values = line.Split(',')
|> Seq.ofArray
|> Seq.skip (1) //the first token is the label. So we have to skip it
|> Seq.map( fun n -> Convert.ToInt32(n))
|> Seq.toList
})
|>Seq.toList
//A generic k-nearest neighbour algorithm
let kNN ( entries : Entry list, newEntry : string * int[] , k : int) =
entries |> List.map( fun x -> ( x.Label, distance (x.Values, snd (newEntry) |>Array.toList )))
|> List.sortBy ( fun x -> snd x)
|> Seq.ofList
|> Seq.take k
|> Seq.countBy (fun x -> fst x)
|> Seq.toList
[<EntryPoint>]
let main argv =
let loaded = loadValues @"C:\Users\mukhsudi\Downloads\train.csv"
//Here is the unknown entry
let newEntry = ("X",[|0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;25;123;245;243;211;45;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;71;227;252;166;47;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;20;197;249;223;47;2;68;232;98;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;48;202;252;155;35;0;15;225;252;80;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;190;252;155;7;0;0;110;252;208;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;123;253;109;0;0;0;68;245;216;18;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;253;224;14;0;0;15;211;252;153;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;54;253;71;0;0;9;237;252;224;7;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;106;253;111;37;91;204;253;252;126;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;18;253;252;235;252;208;253;252;82;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;62;106;106;35;0;255;204;9;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;80;253;89;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;158;253;63;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;43;239;225;21;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;64;252;167;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;169;253;45;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;8;197;252;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;22;252;244;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;22;252;173;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;13;217;121;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0|])
let pixels = snd(newEntry) |> Array.map (fun t -> float t)
//let glabel = "9"
//Let's consider only 5 nearest neighbors
let k = 5
//Getting back the labels for each of the nearest neighbours
let labels = kNN (loaded , newEntry, k)
//Locating the guess. The one with the maximum votes
let guess = fst( List.nth labels 0)
//Answer will be 9
drawDigit (pixels , "I think that it is a " + guess)
0 // return an integer exit code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment