{
  "fetched_at": "2026-10-19T13:27:13Z",
  "source_url": "https://www.kaggle.com/competitions/facial-keypoints-detection/data",
  "pages": [
    {
      "name": "Description",
      "content": "<p>The objective of this task is to predict keypoint positions on face images. This can be used as a building block in several applications, such as:</p>\r\n<ul>\r\n<li>tracking faces in images and video</li>\r\n<li>analysing facial expressions</li>\r\n<li>detecting dysmorphic facial signs for medical diagnosis</li>\r\n<li>biometrics / face recognition</li>\r\n</ul>\r\n<p>Detecing facial keypoints is a very challenging problem.  Facial features vary greatly from one individual to another, and even for a single individual, there is a large amount of variation due to 3D pose, size, position, viewing angle, and illumination conditions. Computer vision research has come a long way in addressing these difficulties, but there remain many opportunities for improvement.</p>\r\n<p>This getting-started competition provides a benchmark data set and an <a href=\"https://www.kaggle.com/c/facial-keypoints-detection/details/getting-started-with-r\"> R tutorial</a> to get you going on analysing face images. <a href=\"https://www.kaggle.com/c/facial-keypoints-detection/details/getting-started-with-r\" style=\"font-size: 1.17em; text-align: center; line-height: 1.4em;\">Get started with R &gt;&gt;</a></p>\r\n<h2>Acknowledgements</h2>\r\n<p>The data set for this competition was graciously provided by <a href=\"http://www.iro.umontreal.ca/~bengioy/yoshua_en/index.html\"> Dr. Yoshua Bengio</a> of the University of Montreal. <span style=\"line-height: 1.4em;\">The tutorial was developed</span><span style=\"line-height: 1.4em;\"> by </span><a href=\"https://www.kaggle.com/users/5018/james-petterson\" style=\"line-height: 1.4em;\">James Petterson</a>.<span style=\"line-height: 1.4em;\"><br /></span></p>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "Evaluation",
      "content": "<h2>Root Mean Squared Error (RMSE)</h2>\r\n<p>Submissions are scored on the root mean squared error. RMSE is very common and is a suitable general-purpose error metric. Compared to the Mean Absolute Error, RMSE punishes large errors:</p>\r\n<p>\\[\\textrm{RMSE} = \\sqrt{\\frac{1}{n} \\sum_{i=1}^{n} (y_i - \\hat{y}_i)^2},\\]</p>\r\n<p>where y hat is the predicted value and y is the original value.</p>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "data-description",
      "content": "<p><span style=\"font-size: 14px; line-height: 1.4em;\">Each predicted keypoint is specified by an (x,y) real-valued pair in the space of pixel indices. There are 15 keypoints, which represent the following elements of the face:</span></p>\r\n<p>left_eye_center, <span>right_eye_center, left_eye_inner_corner, left_eye_outer_corner, right_eye_inner_corner, right_eye_outer_corner, left_eyebrow_inner_end, left_eyebrow_outer_end, right_eyebrow_inner_end, right_eyebrow_outer_end, nose_tip, mouth_left_corner, mouth_right_corner, mouth_center_top_lip, mouth_center_bottom_lip</span></p>\r\n<p>Left and right here refers to the point of view of the subject.</p>\r\n<p>In some examples, some of the target keypoint positions are misssing (encoded as missing entries in the csv, i.e., with nothing between two commas).</p>\r\n<p>The input image is given in the last field of the data files, and consists of a list of pixels (ordered by row), as integers in (0,255). The images are 96x96 pixels.</p>\r\n<p><strong>Data files</strong></p>\r\n<ul>\r\n<li><strong>training.csv:</strong> list of training 7049 images. Each row contains the (x,y) coordinates for 15 keypoints, and image data as row-ordered list of pixels.</li>\r\n<li><strong>test.csv:</strong> list of 1783 test images. Each row contains ImageId and image data as row-ordered list of pixels</li>\r\n<li><strong>submissionFileFormat.csv:</strong> list of 27124 keypoints to predict. Each row contains a RowId, ImageId, FeatureName, Location. FeatureName are \"left_eye_center_x,\" \"right_eyebrow_outer_end_y,\" etc. Location is what you need to predict. </li>\r\n</ul>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "Submission Instructions",
      "content": "<p>Please download the file submissionFileFormat.csv from the data page. This file lists the points whose locations need to be detected.</p>\r\n<p>Submission File Columns</p>\r\n<ul>\r\n<li><strong>Row Id:</strong> integer id for the row</li>\r\n<li><strong>Image Id:</strong> integer id for the image. There are 1783 images in the test set.</li>\r\n<li><strong>Feature Name:</strong> string identifying the facial keypoint, e.g., left_eye_center_x, left_eye_center_y, mouth_bottom_center_lip_x, nose_tip_y</li>\r\n<li><strong>Location:</strong> x- or y-coordinate of the specified feature. <strong>This is the value to be predicted.</strong></li>\r\n</ul>\r\n<h2>Submission file</h2>\r\n<div>Note that you will not be detecting all 30 features (x and y coordinates for 15 facial keypoints) for each image. Some images require fewer keypoints to be detected. Please see the file submissionFileFormat.csv for details. The format looks like this:</div>\r\n<pre>RowId,ImageId,FeatureName,Location\r\n1,1,left_eye_center_x,?\r\n2,1,left_eye_center_y,?\r\n3,1,right_eye_center_x,?\r\n4,1,right_eye_center_y,?\r\netc...\r\n</pre>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "Getting Started With R",
      "content": "<p>In this tutorial we will describe a simple benchmark for this competition, written entirely in R. <span style=\"line-height: 1.4em;\">R is a free software programming language, used widely for statistical computing. It is available for Windows, OS X, Linux and other platforms, and is a favorite amongst Kaggle competitors </span><a style=\"line-height: 1.4em;\" href=\"http://www.kaggle.com/wiki/Software\">tools</a><span style=\"line-height: 1.4em;\">.</span></p>\r\n<h2>The competition</h2>\r\n<p>The goal of the competition is to locate specific keypoints on face images. You should build an algorithm that, given an image of a face, automatically locates where these keypoints are located.</p>\r\n<h2>Download and extract the data</h2>\r\n<p>First you'll need to <a href=\"https://www.kaggle.com/c/facial-keypoints-detection/data\"> get the data</a>. Download <code>training.zip</code>, <code>test.zip</code> and <code> submissionFileFormat.csv</code>, and uncompress them. The <code>training.csv</code> file has 7049 examples of face images with corresponding keypoint locations. We'll use this data to <em>train</em> our algorithm. The <code>test.csv</code> file has face images only, and will be used to test our algorithm, by determining whether we successfully identified the corresponding keypoint locations.</p>\r\n<h2>Reading the data into R</h2>\r\n<p>If you haven't done so yet, install R. You can download it and find installation instructions <a href=\"http://www.r-project.org/\">here</a>.</p>\r\n<p>Now launch R. You should get a prompt similar to this:</p>\r\n<pre>R version 2.15.1 (2012-06-22) -- \"Roasted Marshmallows\"\r\nCopyright (C) 2012 The R Foundation for Statistical Computing\r\nISBN 3-900051-07-0\r\nPlatform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)\r\n\r\nR is free software and comes with ABSOLUTELY NO WARRANTY.\r\nYou are welcome to redistribute it under certain conditions.\r\nType 'license()' or 'licence()' for distribution details.\r\n\r\n  Natural language support but running in an English locale\r\n\r\nR is a collaborative project with many contributors.\r\nType 'contributors()' for more information and\r\n'citation()' on how to cite R or R packages in publications.\r\n\r\nType 'demo()' for some demos, 'help()' for on-line help, or\r\n'help.start()' for an HTML browser interface to help.\r\nType 'q()' to quit R.\r\n\r\n&gt; \r\n</pre>\r\n<p>Let's first create variables to store the path to the files you downloaded:</p>\r\n<pre>data.dir   &lt;- '~/data/kaggle/facial_keypoint_detection/'\r\ntrain.file &lt;- paste0(data.dir, 'training.csv')\r\ntest.file  &lt;- paste0(data.dir, 'test.csv')\r\n</pre>\r\n<p>You should change <code>data.dir</code> to point to the location where you saved the files.</p>\r\n<p>We can now instruct R to read in the 2 csv files. R has a very convenient function for that, so this is very simple:</p>\r\n<pre>d.train &lt;- read.csv(train.file, stringsAsFactors=F)\r\n</pre>\r\n<p>This creates a <em>data.frame</em>, a fundamental structure in R. It is essentially a matrix where each column can have a different type.</p>\r\n<p>We did not tell R what the data type of each column was, so R analyses the data frame and makes guesses. Usually they are right, but it is a good habit to check!</p>\r\n<pre>str(d.train)\r\n\r\n'data.frame':   7049 obs. of  31 variables:\r\n $ left_eye_center_x        : num  66 64.3 65.1 65.2 66.7 ...\r\n $ left_eye_center_y        : num  39 35 34.9 37.3 39.6 ...\r\n $ right_eye_center_x       : num  30.2 29.9 30.9 32 32.2 ...\r\n $ right_eye_center_y       : num  36.4 33.4 34.9 37.3 38 ...\r\n $ left_eye_inner_corner_x  : num  59.6 58.9 59.4 60 58.6 ...\r\n $ left_eye_inner_corner_y  : num  39.6 35.3 36.3 39.1 39.6 ...\r\n $ left_eye_outer_corner_x  : num  73.1 70.7 71 72.3 72.5 ...\r\n $ left_eye_outer_corner_y  : num  40 36.2 36.3 38.4 39.9 ...\r\n $ right_eye_inner_corner_x : num  36.4 36 37.7 37.6 37 ...\r\n $ right_eye_inner_corner_y : num  37.4 34.4 36.3 38.8 39.1 ...\r\n $ right_eye_outer_corner_x : num  23.5 24.5 25 25.3 22.5 ...\r\n $ right_eye_outer_corner_y : num  37.4 33.1 36.6 38 38.3 ...\r\n $ left_eyebrow_inner_end_x : num  57 54 55.7 56.4 57.2 ...\r\n $ left_eyebrow_inner_end_y : num  29 28.3 27.6 30.9 30.7 ...\r\n $ left_eyebrow_outer_end_x : num  80.2 78.6 78.9 77.9 77.8 ...\r\n $ left_eyebrow_outer_end_y : num  32.2 30.4 32.7 31.7 31.7 ...\r\n $ right_eyebrow_inner_end_x: num  40.2 42.7 42.2 41.7 38 ...\r\n $ right_eyebrow_inner_end_y: num  29 26.1 28.1 31 30.9 ...\r\n $ right_eyebrow_outer_end_x: num  16.4 16.9 16.8 20.5 15.9 ...\r\n $ right_eyebrow_outer_end_y: num  29.6 27.1 32.1 29.9 30.7 ...\r\n $ nose_tip_x               : num  44.4 48.2 47.6 51.9 43.3 ...\r\n $ nose_tip_y               : num  57.1 55.7 53.5 54.2 64.9 ...\r\n $ mouth_left_corner_x      : num  61.2 56.4 60.8 65.6 60.7 ...\r\n $ mouth_left_corner_y      : num  80 76.4 73 72.7 77.5 ...\r\n $ mouth_right_corner_x     : num  28.6 35.1 33.7 37.2 31.2 ...\r\n $ mouth_right_corner_y     : num  77.4 76 72.7 74.2 77 ...\r\n $ mouth_center_top_lip_x   : num  43.3 46.7 47.3 50.3 45 ...\r\n $ mouth_center_top_lip_y   : num  72.9 70.3 70.2 70.1 73.7 ...\r\n $ mouth_center_bottom_lip_x: num  43.1 45.5 47.3 51.6 44.2 ...\r\n $ mouth_center_bottom_lip_y: num  84.5 85.5 78.7 78.3 86.9 ...\r\n $ Image                    : chr  \"238 236 237 238 240 240 239 241 241 243 240 239 231 ...\r\n</pre>\r\n<p>In the output above, R lists the column name, followed by its guess at the column type, and then the first few data values in the column. For example, the first column (or variable) in the data frame d.train is named left_eye_center_x. It contains numeric values, and the first two values are 66 and 64.3.</p>\r\n<p>In total, we have 7049 rows, each one with 31 columns. The first 30 columns are keypoint locations, which R correctly identified as numbers. The last one is a string representation of the image, identified as a string. This last column is the reason for the <code>stringsAsFactors</code> argument: if you omit it R might treat this column as a factor (i.e., a <em>category</em>).</p>\r\n<p>By the way, to get help on the syntax of any command in R just prepend a question mark to its name. For example:</p>\r\n<pre>?read.csv\r\n</pre>\r\n<p>will open a full description of the command, and the parameters it expects. You can exit this help quickly too, simply press <code>q</code>.</p>\r\n<p>Back to the data: to get a peek at it you can use the <code>head</code> command, which will display only the top few rows:</p>\r\n<pre>head(d.train)\r\n</pre>\r\n<p>Unfortunately the rightmost column is quite long, so the output is not very readable. Let's save that column as another variable, and remove it from <code>d.train</code>:</p>\r\n<pre>im.train      &lt;- d.train$Image\r\nd.train$Image &lt;- NULL\r\n</pre>\r\n<p>In the first line, we assign a variable <code>im.train</code> the values from <code> d.train$Image</code>. As you can see, R provides us with an easy way to identify the column we want to refer to. <code>d.train</code> is our dataframe, and we want the column called <code>Image</code>. Assigning <code>NULL</code> to a column removes it from the dataframe.</p>\r\n<p>Now let’s try the head command again:</p>\r\n<pre>head(d.train)\r\n\r\n  left_eye_center_x left_eye_center_y right_eye_center_x … \r\n1          66.03356          39.00227           30.22701 …\r\n2          64.33294          34.97008           29.94928 …\r\n3          65.05705          34.90964           30.90379 …\r\n4          65.22574          37.26177           32.02310 …\r\n5          66.72530          39.62126           32.24481 …\r\n6          69.68075          39.96875           29.18355 …\r\n</pre>\r\n<p>As you can see there is one column for each keypoint, and one row for each image.</p>\r\n<p>Now, let’s take a look at the column we moved to <code>im.train</code>. For each image (i.e. in each row) it contains a long string of numbers, where each number represents the intensity of a pixel in the image. Lets look at the first value in the column:</p>\r\n<pre>im.train[1]\r\n\r\n[1] \"238 236 237 238 240 240 239 241 241 243 240…\r\n</pre>\r\n<p>To analyze these further, we convert these strings to integers by splitting them and converting the result to integer:</p>\r\n<pre>as.integer(unlist(strsplit(im.train[1], \" \")))\r\n\r\n[1] 238 236 237 238 240 240 239 241 241 243 240 …\r\n</pre>\r\n<p><code>strsplit</code> splits the string, <code>unlist</code> simplifies its output to a vector of strings and <code>as.integer</code> converts it to a vector of integers.</p>\r\n<p>That works well, but we need to do it for all images, and not only the first one. We could iterate through each record in <code>im.train</code> and apply the <em>string to integers</em> conversion above. However, sequentially processing this conversion can take some time. We can therefore utilize a multi core approach using the <em>doMC</em> library (linux and osx only - if you are working on windows please check <a href=\"https://www.kaggle.com/c/facial-keypoints-detection/forums/t/4613/domc-library-not-available-for-windows/\" title=\"this post\">this post</a> for alternatives).</p>\r\n<p>First, we'll need to install the library with this command:</p>\r\n<pre>install.packages('doMC')\r\n</pre>\r\n<p>After selecting the CRAN mirror you want to use the installation should proceed automatically. Next, we need to load the library and register it</p>\r\n<pre>library(doMC)\r\nregisterDoMC()\r\n</pre>\r\n<p>Now we’re ready to implement the parallelization.</p>\r\n<pre>im.train &lt;- foreach(im = im.train, .combine=rbind) %dopar% {\r\n    as.integer(unlist(strsplit(im, \" \")))\r\n}\r\n</pre>\r\n<p>The <code>foreach</code> loop will evaluate the inner command for each row in <code> im.train</code>, and combine the results with <code>rbind</code> (combine by rows). <code>%dopar%</code> instructs R to do all evaluations in parallel.</p>\r\n<p><code>im.train</code> is now a matrix with 7049 rows (one for each image) and 9216 columns (one for each pixel):</p>\r\n<pre>str(im.train)\r\n\r\n int [1:7049, 1:9216] 238 219 144 193 147 167 109 178 164 226 ...\r\n - attr(*, \"dimnames\")=List of 2\r\n  ..$ : chr [1:7049] \"result.1\" \"result.2\" \"result.3\" \"result.4\" ...\r\n  ..$ : NULL\r\n</pre>\r\n<p>Repeat the process for test.csv, as we are going to need it later. Notice that in the test file, we don’t have the first 30 columns with the keypoint locations.</p>\r\n<pre>d.test  &lt;- read.csv(test.file, stringsAsFactors=F)\r\nim.test &lt;- foreach(im = d.test$Image, .combine=rbind) %dopar% {\r\n    as.integer(unlist(strsplit(im, \" \")))\r\n}\r\nd.test$Image &lt;- NULL\r\n</pre>\r\n<p>It’s a good idea to save the data as a R data file at this point, so you don't have to repeat this process again. We save all four variables into the <code>data.Rd</code> file:</p>\r\n<pre>save(d.train, im.train, d.test, im.test, file='data.Rd')\r\n</pre>\r\n<p>We can reload them at any time with the following command:</p>\r\n<pre>load('data.Rd')\r\n</pre>\r\n<h2>Looking at the data</h2>\r\n<p>Now that the data is loaded let's start looking at the images. Did you notice how the long string comprised of 9216 integers? That’s because each image is a vector of 96*96 pixels (96*96 = 9216).</p>\r\n<p>To visualize each image, we thus need to first convert these 9216 integers into a 96x96 matrix:</p>\r\n<pre>im &lt;- matrix(data=rev(im.train[1,]), nrow=96, ncol=96)\r\n</pre>\r\n<p><code>im.train[1,]</code> returns the first row of <code>im.train</code>, which corresponds to the first training image. <code>rev</code> reverse the resulting vector to match the interpretation of R's <code> image</code> function (which expects the origin to be in the lower left corner). To visualize the image we use R's <code>image</code> function:</p>\r\n<pre>image(1:96, 1:96, im, col=gray((0:255)/255))\r\n</pre>\r\n<p><img src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/3486/media/face1.png\" alt=\"\" /></p>\r\n<p>We can then add some keypoints (from the other 30 columns of the training file) to check if everything is correct so far (here, again, we need to adjust the coordinates for the different origin). Let’s color the coordinates for the eyes and nose:</p>\r\n<pre>points(96-d.train$nose_tip_x[1],         96-d.train$nose_tip_y[1],         col=\"red\")\r\npoints(96-d.train$left_eye_center_x[1],  96-d.train$left_eye_center_y[1],  col=\"blue\")\r\npoints(96-d.train$right_eye_center_x[1], 96-d.train$right_eye_center_y[1], col=\"green\")\r\n</pre>\r\n<p><img src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/3486/media/face1_with_keypoints.png\" alt=\"\" /></p>\r\n<p>Another good check is to see how variable is our data. For example, where are the centers of each nose in the 7049 images? (this takes a while to run):</p>\r\n<pre>for(i in 1:nrow(d.train)) {\r\n    points(96-d.train$nose_tip_x[i], 96-d.train$nose_tip_y[i], col=\"red\")\r\n}\r\n</pre>\r\n<p><img src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/3486/media/face1_with_all_nose_keypoints.png\" alt=\"\" /></p>\r\n<p>Most <em>nose</em> points are concentrated in the central region (as expected), but there are quite a few outliers that deserve further investigation, as they could be labeling errors. Looking at one extreme example we get this:</p>\r\n<pre>idx &lt;- which.max(d.train$nose_tip_x)\r\nim  &lt;- matrix(data=rev(im.train[idx,]), nrow=96, ncol=96)\r\nimage(1:96, 1:96, im, col=gray((0:255)/255))\r\npoints(96-d.train$nose_tip_x[idx], 96-d.train$nose_tip_y[idx], col=\"red\")\r\n</pre>\r\n<p><img src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/3486/media/face4264_outlier.png\" alt=\"\" /></p>\r\n<p>In this case there's no labeling error, but this shows that not all faces are centralized as one might expect.</p>\r\n<p>There's much more that could be analyzed, but let's start building our first algorithm.</p>\r\n<h2>A simple benchmark</h2>\r\n<p>One of the simplest things to try is to compute the mean of the coordinates of each keypoint in the training set and use that as a prediction for all images. This is a very simplistic algorithm, as it completely ignores the images, but we can use it a starting point to build a first submission.</p>\r\n<p>Computing the mean for each column is straightforward with <code>colMeans</code> (<code>na.rm=T</code> tells <code>colMeans</code> to ignore missing values). We get the following values:</p>\r\n<pre>colMeans(d.train, na.rm=T)\r\n\r\n        left_eye_center_x         left_eye_center_y        right_eye_center_x \r\n                 66.35902                  37.65123                  30.30610 \r\n       right_eye_center_y   left_eye_inner_corner_x   left_eye_inner_corner_y \r\n                 37.97694                  59.15934                  37.94475 \r\n  left_eye_outer_corner_x   left_eye_outer_corner_y  right_eye_inner_corner_x \r\n                 73.33048                  37.70701                  36.65261 \r\n right_eye_inner_corner_y  right_eye_outer_corner_x  right_eye_outer_corner_y \r\n                 37.98990                  22.38450                  38.03350 \r\n left_eyebrow_inner_end_x  left_eyebrow_inner_end_y  left_eyebrow_outer_end_x \r\n                 56.06851                  29.33268                  79.48283 \r\n left_eyebrow_outer_end_y right_eyebrow_inner_end_x right_eyebrow_inner_end_y \r\n                 29.73486                  39.32214                  29.50300 \r\nright_eyebrow_outer_end_x right_eyebrow_outer_end_y                nose_tip_x \r\n                 15.87118                  30.42817                  48.37419 \r\n               nose_tip_y       mouth_left_corner_x       mouth_left_corner_y \r\n                 62.71588                  63.28574                  75.97071 \r\n     mouth_right_corner_x      mouth_right_corner_y    mouth_center_top_lip_x \r\n                 32.90040                  76.17977                  47.97541 \r\n   mouth_center_top_lip_y mouth_center_bottom_lip_x mouth_center_bottom_lip_y \r\n                 72.91944                  48.56947                  78.97015 \r\n</pre>\r\n<p>To build a submission file we need to apply these computed coordinates to the test instances:</p>\r\n<pre>p           &lt;- matrix(data=colMeans(d.train, na.rm=T), nrow=nrow(d.test), ncol=ncol(d.train), byrow=T)\r\ncolnames(p) &lt;- names(d.train)\r\npredictions &lt;- data.frame(ImageId = 1:nrow(d.test), p)\r\nhead(predictions)\r\n\r\n  ImageId left_eye_center_x left_eye_center_y right_eye_center_x …\r\n1       1          66.35902          37.65123            30.3061 …\r\n2       2          66.35902          37.65123            30.3061 …\r\n3       3          66.35902          37.65123            30.3061 …\r\n4       4          66.35902          37.65123            30.3061 …\r\n5       5          66.35902          37.65123            30.3061 …\r\n6       6          66.35902          37.65123            30.3061 … \r\n</pre>\r\n<p>The expected submission format has one one keypoint per row, but we can easily get that with the help of the <em>reshape2</em> library:</p>\r\n<pre>install.packages('reshape2')\r\nlibrary(reshape2)\r\nsubmission &lt;- melt(predictions, id.vars=\"ImageId\", variable.name=\"FeatureName\", value.name=\"Location\")\r\nhead(submission)\r\n\r\n  ImageId       FeatureName Location\r\n1       1 left_eye_center_x 66.35902\r\n2       2 left_eye_center_x 66.35902\r\n3       3 left_eye_center_x 66.35902\r\n4       4 left_eye_center_x 66.35902\r\n5       5 left_eye_center_x 66.35902\r\n6       6 left_eye_center_x 66.35902\r\n</pre>\r\n<p>We then join this with the sample submission file to preserve the same order of entries and save the result:</p>\r\n<pre>example.submission &lt;- read.csv(paste0(data.dir, 'submissionFileFormat.csv'))\r\nsub.col.names      &lt;- names(example.submission)\r\nexample.submission$Location &lt;- NULL\r\nsubmission &lt;- merge(example.submission, submission, all.x=T, sort=F)\r\nsubmission &lt;- submission[, sub.col.names]\r\nwrite.csv(submission, file=\"submission_means.csv\", quote=F, row.names=F)\r\n</pre>\r\n<p>If you submit this file you will get a leaderboard score of <em>3.96244</em>. Not a very exciting result, but shows us that the submission format is correct.</p>\r\n<h2>Using image patches</h2>\r\n<p>The above method was rather simplistic, and didn’t analyse the images at all. Said another way, we didn’t use the information about the intensity of each pixel to identify the keypoints. Let's try to build an algorithm that makes use of this rich data.</p>\r\n<p>To simplify we will first focus on a single keypoint: <em>left_eye_center</em>.</p>\r\n<p>The idea is to extract a patch around this keypoint in each image, and average the result. This <em>average_patch</em> can then be used as a mask to search for the keypoint in test images.</p>\r\n<p>We start defining some parameters:</p>\r\n<pre>coord      &lt;- \"left_eye_center\"\r\npatch_size &lt;- 10\r\n</pre>\r\n<p><code>coord</code> is the keypoint we are working on, and <code>patch_size</code> is the number of pixels we are going to extract in each direction around the center of the keypoint. So 10 means we will have a square of 21x21 pixels (10+1+10). This will become more clear with an example:</p>\r\n<pre>coord_x &lt;- paste(coord, \"x\", sep=\"_\")\r\ncoord_y &lt;- paste(coord, \"y\", sep=\"_\")\r\npatches &lt;- foreach (i = 1:nrow(d.train), .combine=rbind) %do% {\r\n    im  &lt;- matrix(data = im.train[i,], nrow=96, ncol=96)\r\n    x   &lt;- d.train[i, coord_x]\r\n    y   &lt;- d.train[i, coord_y]\r\n    x1  &lt;- (x-patch_size)\r\n    x2  &lt;- (x+patch_size)\r\n    y1  &lt;- (y-patch_size)\r\n    y2  &lt;- (y+patch_size)\r\n    if ( (!is.na(x)) &amp;&amp; (!is.na(y)) &amp;&amp; (x1&gt;=1) &amp;&amp; (x2&lt;=96) &amp;&amp; (y1&gt;=1) &amp;&amp; (y2&lt;=96) )\r\n    {\r\n        as.vector(im[x1:x2, y1:y2])\r\n    }\r\n    else\r\n    {\r\n        NULL\r\n    }\r\n}\r\nmean.patch &lt;- matrix(data = colMeans(patches), nrow=2*patch_size+1, ncol=2*patch_size+1)\r\n</pre>\r\n<p>This <em>foreach</em> loop will get each image and:</p>\r\n<ul>\r\n<li>extract the coordinates of the keypoint: <code>x</code> and <code>y</code></li>\r\n<li>compute the coordinates of the patch: <code>x1</code>, <code>y1</code>, <code> x2</code> and <code>y2</code></li>\r\n<li>check if the coordinates are available (<code>is.na</code>) and are inside the image</li>\r\n<li>if yes, return the image patch as a vector; if no, return NULL</li>\r\n</ul>\r\n<p>All the non-NULL vectors will then be combined with <code>rbind</code>, which concatenates them as rows. The result <code>patches</code> will be a matrix where each row is a patch of an image. We then compute the mean of all images with <code>colMeans</code>, put back in matrix format and store in <code>mean.patch</code>. You can then visualize the result with <code>image</code>:</p>\r\n<pre>image(1:21, 1:21, mean.patch[21:1,21:1], col=gray((0:255)/255))\r\n</pre>\r\n<p><img src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/3486/media/left_eye_center_mean_patch.png\" alt=\"\" /></p>\r\n<p>And it does look like an eye! This is the average left eye computed across our 7049 images.</p>\r\n<p>Now we can use this <em>average_patch</em> to search for the same keypoint in the test images. First we define another parameter:</p>\r\n<pre>search_size &lt;- 2\r\n</pre>\r\n<p><code>search_size</code> indicates how many pixels we are going to move in each direction when searching for the keypoint. We will center the search on the average keypoint location, and go <code>search_size</code> pixels in each direction:</p>\r\n<pre>mean_x &lt;- mean(d.train[, coord_x], na.rm=T)\r\nmean_y &lt;- mean(d.train[, coord_y], na.rm=T)\r\nx1     &lt;- as.integer(mean_x)-search_size\r\nx2     &lt;- as.integer(mean_x)+search_size\r\ny1     &lt;- as.integer(mean_y)-search_size\r\ny2     &lt;- as.integer(mean_y)+search_size\r\n</pre>\r\n<p>In this particular case the search will be from (64,35) to (68,39). We can use <code>expand.grid</code> to build a data frame with all combinations of <code>x</code>'s and <code>y</code>'s:</p>\r\n<pre>params &lt;- expand.grid(x = x1:x2, y = y1:y2)\r\nparams\r\n\r\n    x  y\r\n1  64 35\r\n2  65 35\r\n3  66 35\r\n4  67 35\r\n5  68 35\r\n6  64 36\r\n7  65 36\r\n8  66 36\r\n9  67 36\r\n10 68 36\r\n11 64 37\r\n12 65 37\r\n13 66 37\r\n14 67 37\r\n15 68 37\r\n16 64 38\r\n17 65 38\r\n18 66 38\r\n19 67 38\r\n20 68 38\r\n21 64 39\r\n22 65 39\r\n23 66 39\r\n24 67 39\r\n25 68 39\r\n</pre>\r\n<p>Given a test image we need to try all these combinations, and see which one best <em>matches</em> the <em>average_patch</em>. We will do that by taking patches of the test images around these points and measuring their <em>correlation</em> with the <em>average_patch</em>. Take the first test image as an example:</p>\r\n<pre>im &lt;- matrix(data = im.test[1,], nrow=96, ncol=96)\r\n\r\nr  &lt;- foreach(j = 1:nrow(params), .combine=rbind) %dopar% {\r\n    x     &lt;- params$x[j]\r\n    y     &lt;- params$y[j]\r\n    p     &lt;- im[(x-patch_size):(x+patch_size), (y-patch_size):(y+patch_size)]\r\n    score &lt;- cor(as.vector(p), as.vector(mean.patch))\r\n    score &lt;- ifelse(is.na(score), 0, score)\r\n    data.frame(x, y, score)\r\n}\r\n</pre>\r\n<p>Inside the for loop, given a coordinate we extract an image patch <code>p</code> and compare it to the <em>average_patch</em> with <code>cor</code>. The <code>ifelse</code> is necessary for the cases where all the image patch pixels have the same intensity, as in this case <code>cor</code> returns <code>NA</code>. The result will look like this:</p>\r\n<pre>r\r\n\r\n    x  y     score\r\n1  64 35 0.1017430\r\n2  65 35 0.1198157\r\n3  66 35 0.1376269\r\n4  67 35 0.1351847\r\n5  68 35 0.1119015\r\n6  64 36 0.2769096\r\n7  65 36 0.2884035\r\n8  66 36 0.2923847\r\n9  67 36 0.2741814\r\n10 68 36 0.2333830\r\n11 64 37 0.4410122\r\n12 65 37 0.4560440\r\n13 66 37 0.4520532\r\n14 67 37 0.4189839\r\n15 68 37 0.3632465\r\n16 64 38 0.5559125\r\n17 65 38 0.5715887\r\n18 66 38 0.5675701\r\n19 67 38 0.5317430\r\n20 68 38 0.4711673\r\n21 64 39 0.6115627\r\n22 65 39 0.6131023\r\n23 66 39 0.6063069\r\n24 67 39 0.5794715\r\n25 68 39 0.5276036\r\n</pre>\r\n<p>Now all we need to do is return the coordinate with the highest score:</p>\r\n<pre>best &lt;- r[which.max(r$score), c(\"x\", \"y\")]\r\nbest\r\n\r\n    x  y\r\n22 65 39\r\n</pre>\r\n<p>To build a submission the whole procedure has to be repeated for each keypoint and for each test image. We won't explain this in detail here, but you can download a complete solution from <a href=\"https://gist.github.com/jpetterson/776aba5d190d0fe84fdd\">here</a>. After downloading it, adjust the location of the data in the top of the file and run the code with</p>\r\n<pre>Rscript --vanilla tutorial.R\r\n</pre>\r\n<p>It takes a while to run (about 6 minutes in a quad core laptop), and once finished it will create the file <code>submission_search.csv</code>. If you submit it you should get a leaderboard score of <em>3.80685</em>. It's a small improvement when compared to the result of the means benchmark (<em>3.96244</em>), but that is often the case when exploring new methods.</p>\r\n<h2>Experimenting without making submissions</h2>\r\n<p>Most competitions impose a limit on the number of submissions per day to avoid overfitting to the test data. I common approach to overcome this limitation is to split the training data in two sets: one for training (say, 80% of the data, randomly chosen), and another for testing (the rest). We then train our algorithm using only the first set, and can then use the second one to evaluate the performance without making a submission.</p>\r\n<p>This can be easily done by replacing this code</p>\r\n<pre>d.train    &lt;- read.csv(train.file, stringsAsFactors=F)\r\nd.test     &lt;- read.csv(test.file,  stringsAsFactors=F)\r\nim.train   &lt;- foreach(im = d.train$Image, .combine=rbind) %dopar% {\r\n    as.integer(unlist(strsplit(im, \" \")))\r\n}\r\nim.test    &lt;- foreach(im = d.test$Image, .combine=rbind) %dopar% {\r\n    as.integer(unlist(strsplit(im, \" \")))\r\n}\r\nd.train$Image &lt;- NULL\r\nd.test$Image  &lt;- NULL\r\n</pre>\r\n<p>with this</p>\r\n<pre>d  &lt;- read.csv(train.file, stringsAsFactors=F)\r\nim &lt;- foreach(im = d$Image, .combine=rbind) %dopar% {\r\n    as.integer(unlist(strsplit(im, \" \")))\r\n}\r\nd$Image &lt;- NULL\r\nset.seed(0)\r\nidxs     &lt;- sample(nrow(d), nrow(d)*0.8)\r\nd.train  &lt;- d[idxs, ]\r\nd.test   &lt;- d[-idxs, ]\r\nim.train &lt;- im[idxs,]\r\nim.test  &lt;- im[-idxs,]\r\nrm(\"d\", \"im\")\r\n</pre>\r\n<p><code>set.seed</code> fixes the pseudo random number generator seed, so later on you can reproduce this with exactly the same results if needed. Everything else stays the same. Once you have your predictions</p>\r\n<pre>p &lt;- matrix(data=colMeans(d.train, na.rm=T), nrow=nrow(d.test), ncol=ncol(d.train), byrow=T)\r\n</pre>\r\n<p>You can then computed the <a href=\"https://www.kaggle.com/wiki/RootMeanSquaredError\"> RMSE</a> on your test set:</p>\r\n<pre>sqrt(mean((d.test-p)^2, na.rm=T))\r\n\r\n[1] 3.758999\r\n</pre>\r\n<p>This is a good proxy of the score you would get on the leaderboard (assuming the data on the supplied train and test sets follow the same distribution), so you can use it to compare different methods without making submissions.</p>\r\n<h2>Next steps</h2>\r\n<p>The method described here is very simple, and won't take you to the top of the leaderboard, so what can you do next?</p>\r\n<p>The literature on Computer Vision is vast and can be intimidating. A good starting point, though, is Viola and Jones' <a href=\"http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.110.4868\"> seminal paper</a> on object detection. Their proposed framework works quite well, and has an open source implementation available as part of the <a href=\"http://opencv.willowgarage.com/wiki/\">opencv project</a>.</p>\r\n<p>In opencv's website you can find a <a href=\"http://docs.opencv.org/doc/user_guide/ug_traincascade.html\"> user guide</a> for training a new object detector. And if you google for <code>opencv haartraining</code> you'll find other more detailed tutorials, such as <a href=\"http://note.sonots.com/SciSoftware/haartraining.html\">this one</a>.</p>\r\n<p>The implementation also comes with pre-trained classifiers, which you can easily try. See, for example, the result of applying the pre-trained eye detector to one of the images:</p>\r\n<p><img src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/3486/media/opencv_detection.png\" alt=\"\" /></p>\r\n<p>Good luck with the competition!</p>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "rules",
      "content": "\r\n\t<!-- Begin Base Rules -->\r\n    <h3>One account per participant</h3>\r\n    <p>You cannot sign up to Kaggle from multiple accounts and therefore you cannot submit from multiple accounts.</p>\r\n    <h3>No private sharing outside teams</h3>\r\n    <p>\r\n        Privately sharing code or data outside of teams is not permitted.\r\n        It's okay to share code if made available to all participants on the forums.\r\n    </p>\r\n    <h3>Team Mergers</h3>\r\n    <p>\r\n        Team mergers are allowed and can be performed by the team leader. In order to merge, the combined team must have a total submission count less than or equal to the maximum allowed as of the merge date. The maximum allowed is the number of submissions per day multiplied by the number of days the competition has been running.<br/>\r\n    </p>\r\n\r\n    <h3>Team Limits</h3>\r\n    <p>There is no maximum team size.</p>\r\n    <h3>Submission Limits</h3>\r\n    <p>You may submit a maximum of 5 entries per day.</p>\r\n    <p>You may select up to 5 final submissions for judging.</p>\r\n    <h3>Competition Timeline</h3>\r\n    <p>Start Date: <strong>5/7/2013 2:24 PM UTC</strong></p>\r\n    <p>Merger Deadline: <strong>None</strong></p>\r\n    <p>Entry Deadline: <strong>None</strong></p>\r\n    <p>End Date: <strong>1/7/2017 12:00 AM UTC</strong></p>\r\n\t<!-- End Base Rules -->\r\n",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    },
    {
      "name": "Deep Learning Tutorial",
      "content": "<h2>The Tutorial</h2>\r\n<p>Our friend <a href=\"http://danielnouri.org/\">Daniel Nouri</a>, founder of <a href=\"http://naturalvision.de/\">Natural Vision</a> and top contender on <a href=\"https://www.kaggle.com/c/facial-keypoints-detection/leaderboard\">the leaderboard</a>, has written a <a href=\"http://danielnouri.org/notes/2014/12/17/using-convolutional-neural-nets-to-detect-facial-keypoints-tutorial/\">tutorial blog post</a> on this competition. The tutorial outlines how to use convolutional neural nets to detect facial key points on this competition's dataset. We strongly encourage you to follow Daniel's tutorial, step through the exercises, and learn how to build different network architectures. </p>\r\n<p>Daniel's blog post features <a href=\"https://github.com/benanne/Lasagne\">Lasagne</a>, which uses Python and <a href=\"http://deeplearning.net/software/theano/\">Theano</a>. Before tackling the tutorial, you'll need:</p>\r\n<ol>\r\n<li>A GPU (either on your computer, or we'll teach you how to run on AWS)</li>\r\n<li>To configure your GPU to run Theano</li>\r\n</ol>\r\n<p>Below, we walk you through how to complete both of these prerequisites. </p>\r\n<h2>What if I don't have GPU?</h2>\r\n<p>Not everyone has a GPU - it's primarily used for gaming or heavy 3D visualization. The GPU is orders of magnitude faster than the cpu for math operations (such as matrix multiplication), which is essential for many machine learning algorithms. In this tutorial, most of the training of neural nets needs to be run on a GPU, otherwise it could take hours to train.  </p>\r\n<p>If you don't have a GPU, you can spin up some <a href=\"http://aws.amazon.com/\">Amazon Web Services</a> instances to run this tutorial and pay a small fee for the computing hours. </p>\r\n<p>Log into your <a href=\"console.aws.amazon.com\">AWS management console</a> and click over to EC2. There are two options for creating your instance:</p>\r\n<ul>\r\n<li><span style=\"font-size: 1em; line-height: 1.5em;\">On demand instances: Uninterrupted running of your code. More expensive at </span><span style=\"font-size: 1em; line-height: 1.5em;\">$0.702 per Instance Hour.</span></li>\r\n<li><span style=\"font-size: 1em; line-height: 1.5em;\">Spot instances:  This option gives you left-over compute power at a much cheaper rate. Use this option if you can handle potential interrupts. It's at around $0.0031 per Instance Hour.</span></li>\r\n</ul>\r\n<h3>Configuring your AWS instance to run Theano</h3>\r\n<p>There are quite a few steps to configure an AWS instance to run CUDA-GPU successfully. We have found using <a href=\"http://markus.com/install-theano-on-aws/\">these steps</a> very useful. However, it can be a bit cumbersome to run so many steps every time. The <a href=\"http://markus.com/\">author</a> has graciously provided an image (AMI) for his configuration, so you can launch it as a starting point (and skip that tutorial). </p>\r\n<h4>Step 1: Go to <a href=\"console.aws.amazon.com/ec2/\">AWS EC2 Dashboard</a> and click \"Launch Instance\"</h4>\r\n<p><img src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/3486/media/Screen%20Shot%202015-01-06%20at%2011.30.55%20AM.png\" width=\"552\" height=\"289\" /></p>\r\n<h4>Step 2: Search for the configured image ami-1f3e225a</h4>\r\n<p><img src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/3486/media/Screen%20Shot%202015-01-06%20at%2011.51.02%20AM.png\" alt=\"\" width=\"553\" height=\"223\" /></p>\r\n<p><img src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/3486/media/Screen%20Shot%202015-01-06%20at%2011.51.13%20AM.png\" alt=\"\" width=\"553\" /></p>\r\n<h4>Step 3: Select your GPU instance (g2.2xlarge)</h4>\r\n<p><img src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/3486/media/Screen%20Shot%202015-01-06%20at%2011.46.24%20AM.png\" alt=\"\" width=\"533\" /></p>\r\n<h4>Step 4: Review, launch! Now you should be able to connect. </h4>\r\n<p><img src=\"https://storage.googleapis.com/kaggle-media/competitions/kaggle/3486/media/Screen%20Shot%202015-01-06%20at%2011.48.05%20AM.png\" alt=\"\" width=\"533\" /></p>\r\n<h4>Step 5: Follow AWS instructions to connect</h4>\r\n<p>You should see instruction to ssh into the server similar to this:</p>\r\n<pre>ssh -i my-key.pem ubuntu@[DNS]</pre>\r\n<p>and you're connected!</p>\r\n<h4>Step 6: Configure your AWS instance to run the tutorial</h4>\r\n<p>I have scripted the configuration in this <a href=\"https://github.com/wendykan/AWSGPU_DeepLearning\">github repo</a>. All you need to do is to clone this repository, and run the setup.sh script. </p>\r\n<p>Please pay special attention for <a href=\"http://www.kaggle.com/c/belkin-energy-disaggregation-competition/forums/t/5118/downloading-data-via-wget/49609\">downloading the data and putting them on AWS server</a>. You need to copy-paste from your browser's cookie into a file called cookie.txt in order to get the correct data files. The downloading step is included in setup.sh, but you need to copy-paste your cookie.txt file yourself. It is described in the README file in the repository. </p>\r\n<h4>Step 7: Go on to <a href=\"http://danielnouri.org/notes/2014/12/17/using-convolutional-neural-nets-to-detect-facial-keypoints-tutorial/\">Daniel's tutorial</a> and have fun!</h4>\r\n<h4>Step 8: Don't forget to terminate your AWS instance. <strong>Otherwise you get charged. </strong></h4>\r\n<p>Kaggle is not responsible for any charges incurred from running this tutorial. </p>\r\n<p>__________________________________________________________________________________</p>\r\n<h6>Daniel Nouri is the founder of <a href=\"http://naturalvision.de/\">Natural Vision</a>, a company that builds cutting edge machine learning solutions.</h6>",
      "isPublished": false,
      "hasIsPublished": false,
      "postTitle": "",
      "hasPostTitle": false,
      "mimeType": "",
      "hasMimeType": false
    }
  ]
}