{
  "id": 10853,
  "title": "DEVICE_GEO_COUNTRY",
  "url": "/competitions/avazu-ctr-prediction/discussion/10853",
  "author_name": "",
  "post_date": "2014-11-06T15:13:00.807Z",
  "votes": null,
  "comment_count": 26,
  "views": 7230,
  "content": "<p>Hi everybody!</p>\n<p>is there any way to know that is representing&nbsp;the values of device_geo_country variable? I mean, there are 232 different values for all length 8... then, every different value is a country? or maybe the first digits refers to the country and the following to the regi&#243;n?, if so, how many and which digits represent the country??</p>\n<p>thanks!</p>",
  "messages": [
    {
      "id": "57405",
      "postDate": "11/06/2014 15:13:00",
      "content": "<p>Hi everybody!</p>\n<p>is there any way to know that is representing&nbsp;the values of device_geo_country variable? I mean, there are 232 different values for all length 8... then, every different value is a country? or maybe the first digits refers to the country and the following to the regi&#243;n?, if so, how many and which digits represent the country??</p>\n<p>thanks!</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57411",
      "postDate": "11/06/2014 16:02:30",
      "content": "<p>It could be interesting to correlate each of the levels of country with peak activity time of day, and at least infer longitude for each country...</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57424",
      "postDate": "11/06/2014 17:23:44",
      "content": "<p>Here is a plot of normalized hourly click&nbsp;ratios (ie click ratio for each hour / average ratio) for each country:</p>\n<p><img src=\"http://img.techpowerup.org/141106/click_ratio763.png\" alt=\"click ratios\" width=\"400\" height=\"474\"></p>\n<p>Not exactly what I would have expected to see. There seems to be some kind of general trend and not huge variations between the countries etc.</p>\n<p>Edit: Hmm, maybe this could be just a&nbsp;consequence of the reported subsampling of the data</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57428",
      "postDate": "11/06/2014 18:45:41",
      "content": "<p>device_geo_country &nbsp;= 'dc634e20'</p>\n<p><img src=\"http://img.techpowerup.org/141106/dc634e20.png\" alt width=\"795\" height=\"596\"></p>\n<p>I arbitrarily select several device-geo-country and find most of them have statistics like the picture above, but the location of peak is different.</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57453",
      "postDate": "11/07/2014 02:45:32",
      "content": "<p>It's at least plausible that they are countries - ISO 3166 tabulates each recognised nation as a two character alpha, a three character alpha and a three character numeric - total 8 characters - and has a listing for around 250 nation-like entities.</p>\n<p>At the same time, it is also possible that a few countries - e.g. the USA - could be encoded at the state level. Not uncommon for online forms to request the user's country, and then request the user's state if and only they identify as from the US and/or a handful of other large countries.</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57460",
      "postDate": "11/07/2014 10:09:39",
      "content": "<p>Hi OzRob,</p>\n<p>It really is a good idea but can not find the correspondence between the two codes!</p>\n\n<p>For example, dc634e20?</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57486",
      "postDate": "11/07/2014 20:16:26",
      "content": "<p>Here's the top 10 countries in training data:</p>\n<p>1 13b5bfe9 India //md5('in') = &quot;13b5bfe96f3e2fe411c9f66f4a582adf&quot;<br>2 b80bb774 Indonesia<br>3 0b3b97fa United States<br>4 959848ca South Africa<br>5 1cd3c693 Pakistan<br>6 dc634e20 Brazil<br>7 c12e01f2 Saudi Arabia<br>8 795237fd Iraq<br>9 dcf0d7d2 Korea, Republic Of<br>10 dd07de85 Peru</p>\n\n<p>Now, let's go crack the other columns :)</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57492",
      "postDate": "11/07/2014 22:34:02",
      "content": "<p>B Yang: it is amazing that you are decoding the top country - very curious about how you managed to do so if you don't mind sharing the technique :)</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57493",
      "postDate": "11/07/2014 22:51:23",
      "content": "<p>[quote=DerekZH;57492]</p>\n<p>B Yang: it is amazing that you are decoding the top country - very curious about how you managed to do so if you don't mind sharing the technique :)</p>\n<p>[/quote]</p>\n\n<p>He's using the first 8 chars from the md5 hash (as stated in the comment from&nbsp;line 1).</p>\n<p>MD5 (&quot;in&quot;) = 13b5bfe96f3e2fe411c9f66f4a582adf<br>MD5 (&quot;id&quot;) = b80bb7740288fda1f201890375a60c8f<br>MD5 (&quot;us&quot;) = 0b3b97fa66886c5688ee4ae80ec0c3c2<br>MD5 (&quot;za&quot;) = 959848ca10cc8a60da818ac11523dc63<br>MD5 (&quot;pk&quot;) = 1cd3c693132f4c31b5b5e5f4c5eed6bd<br>MD5 (&quot;br&quot;) = dc634e2072827fe0b5be9a2063390544<br>MD5 (&quot;sa&quot;) = c12e01f2a13ff5587e1e9e4aedb8242d<br>MD5 (&quot;iq&quot;) = 795237fd9d107e63cd19b0db0f2fba2f<br>MD5 (&quot;kr&quot;) = dcf0d7d2cd120bf42580d43f29785dd3<br>MD5 (&quot;pe&quot;) = dd07de8561395a7c37f8fcc1752d45e1</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57494",
      "postDate": "11/07/2014 23:38:41",
      "content": "<p>Full list</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57499",
      "postDate": "11/08/2014 03:50:46",
      "content": "<p>[quote=Nissan Pow;57493]</p>\n<p>He's using the first 8 chars from the md5 hash (as stated in the comment from&nbsp;line 1).</p>\n<p>[/quote]</p>\n<p>Yes, you hash the likely suspects and see if the leading bytes are in the data. For example, the top 5 device_os:</p>\n<ul>\n<li>c31b3236&nbsp; android</li>\n<li>2f3f71f2&nbsp; rim os</li>\n<li>990c0803&nbsp; windows phone os</li>\n<li>9e304d4e&nbsp; ios</li>\n<li>08145b8c&nbsp; symbian os</li>\n</ul>\n<p>And the top 10 device_make:</p>\n<ul>\n<li>fe546279&nbsp; samsung</li>\n<li>3d517f89</li>\n<li>a608b9c4&nbsp; lg</li>\n<li>026af9dc&nbsp; micromax</li>\n<li>33561003&nbsp; sony</li>\n<li>0c23a8bf&nbsp; nokia</li>\n<li>c1aafc7e&nbsp; huawei</li>\n<li>36dfa7ba&nbsp; rim</li>\n<li>4aab4dc9&nbsp; htc</li>\n<li>f3c0fa6b&nbsp; alcatel</li>\n</ul>\n<p>I wonder what the #2 device_make is, I suspect it's something like '-unknown-'. You can go to this web site:</p>\n<p>&nbsp;&nbsp;&nbsp; http://www.md5hashgenerator.com/index.php</p>\n<p>enter your guess and click on &quot;Generate MD5 Hash&quot;.</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57552",
      "postDate": "11/09/2014 12:37:24",
      "content": "<p>How can one IP have two DEVICE_GEO_COUNTRY values associated with it?</p>\n<p>For eg. c1b8122b DEVICE_IP&nbsp;has&nbsp;b80bb774 and&nbsp;0b3b97fa.</p>\n<p>Cheers!</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57591",
      "postDate": "11/10/2014 11:46:18",
      "content": "<p>I would suspect that the owner of that phone has been in more than one country during the time period covered by the dataset. Whenever I travel I spend a fair amount of time messing around on my phone while waiting in airports, both while waiting for departure and waiting to get through arrivals - i.e. in 2 countries! I usually have data turned off when abroad due to roaming costs, but guess not everyone does so.</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57607",
      "postDate": "11/10/2014 14:54:27",
      "content": "<p>I see, but the IP of your phone is differnet in Paris and London, the geolocation is different. The question is how can the same&nbsp;IP have two different geolocations.</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57613",
      "postDate": "11/10/2014 16:00:21",
      "content": "<p>ivo@</p>\n<p>ivo wrote:</p>\n<p>The question is how can the same IP have two different geolocations.</p>\n<p>_________________________________________________________&nbsp;</p>\n<p>I think - this is not possible</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57622",
      "postDate": "11/10/2014 17:22:08",
      "content": "<p>probably means they are going state-wise in some countries (india). and some small states in india share ip geolocations.</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57623",
      "postDate": "11/10/2014 17:34:26",
      "content": "<p>on second thoughts there are 233 country codes and 232 values in the file. i'm guessing they are excluding only china.</p>\n<p>https://en.wikipedia.org/wiki/List_of_countries_by_IPv4_address_allocation</p>\n<p>there are 19 countries with 0 IPs. these probably use IP from nearby countries.</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57650",
      "postDate": "11/10/2014 19:26:44",
      "content": "<p>Given the initial data debacle, I was fully expecting something like this. Seriously guys, you did not salt your hashes? Did you&nbsp;expect nobody would try using common hashes on simple fields to deanonymize the data? Like it has happened every single time unsalted hashes have been used in a competition? Guys.</p>\n<p>In case you're wondering, the reason this is problematic from a privacy perspective, is that by brute-forcing the device_ip column (by hashing a few billion IPs that have been active recently and matching the hashes with the Avazu data) and the&nbsp;site_domain column (by hashing the Alexa top 1M website domains and matching them against the Avazu data), you get access to the web histories of a few hundred thousand people (assuming a reasonable brute-forcing success rate), all personally identifiable. And that's bad. &nbsp;</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57686",
      "postDate": "11/10/2014 21:55:19",
      "content": "<p>Why bother with hashing at all ? In my view, the right way is&nbsp;to map each unique value to an incrementing integer ID:</p>\n<p style=\"padding-left: 30px\"><code>int new_id=0;<br>dictionary d;<br>for (each datum in data column) {<br>&nbsp; if (!d.contains_key(datum)) {<br>&nbsp;&nbsp;&nbsp;&nbsp; d[datum]=new_id;&nbsp;new_id++;<br>&nbsp; }<br>&nbsp; mapped_value=d[datum];<br>}<br></code></p>\n<p>This approach has the following advantages:</p>\n<ul>\n<li>Faster processing compared to non-trivial hashing.</li>\n<li>Smaller resulting dataset.</li>\n<li>Resistance to cracking.</li>\n</ul>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57687",
      "postDate": "11/10/2014 22:03:32",
      "content": "<p>[quote=B Yang;57686]</p>\n<p>Why bother with hashing at all ? In my view, the right way is&nbsp;to map each unique value to an incrementing integer ID:</p>\n<p style=\"padding-left: 30px\"><code>int new_id=0;<br>dictionary d;<br>for (each datum in data column) {<br>&nbsp; if (!d.contains_key(datum)) {<br>&nbsp;&nbsp;&nbsp;&nbsp; d[datum]=new_id;&nbsp;new_id++;<br>&nbsp; }<br>&nbsp; mapped_value=d[datum];<br>}<br></code></p>\n<p>This approach has the following advantages:</p>\n<ul>\n<li>Faster processing compared to non-trivial hashing.</li>\n<li>Smaller resulting dataset.</li>\n<li>Resistance to cracking.</li>\n</ul>\n<p>[/quote]</p>\n\n<p>Agreed. I usually do this for long hashes anyway as it frees up more memory</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57688",
      "postDate": "11/10/2014 22:03:39",
      "content": "<p>@B Yang: Actually this how I first processed this dataset. I sorted ids in decreasing order (so 0 value is the most frequent). It reduced the size of the data by 50%. I don't know if it helps someone but I'm attaching the script to do this. The list of columns is wrong (they changed the column labels) and I don't have the correct list.</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57690",
      "postDate": "11/10/2014 22:43:34",
      "content": "<p>[quote=Pawe&#322;;57688]</p>\n<p>@B Yang: Actually this how I first processed this dataset. I sorted ids in decreasing order (so 0 value is the most frequent). It reduced the size of the data by 50%. ...</p>\n<p>[/quote]</p>\n<p>I do something similar see:</p>\n<p><a href=\"https://github.com/gatapia/py_ml_utils/blob/master/pandas_extensions.py\" target=\"_blank\">pandas_extensions.py</a></p>\n\n<p>These are pandas extension methods, it includes a:</p>\n<p><code>DataFrame.compress(aggresiveness=0,to_sparse=False)</code></p>\n<p>method that reduces size of data by 60-85% it does the following:</p>\n<ul>\n<li><span style=\"font-size: 16.3636360168457px; line-height: 1.4;\">Sorts categoricals by frequency and converts to ints with highest freq first</span></li>\n<li><span style=\"font-size: 16.3636360168457px; line-height: 1.4;\">Uses lowest possible dtype for each column (instead of 64 bit floats by default I can get some columns down to 8bits)</span></li>\n<li><span style=\"font-size: medium\"><span style=\"line-height: 1.4\">It has an&nbsp;</span></span><span style=\"line-height: 20.8264446258545px\">aggressiveness</span><span style=\"font-size: medium\"><span style=\"line-height: 1.4\">&nbsp;attribute which will convert float64 -&gt; 32 or 16 bit depending on&nbsp;</span>aggressiveness<span style=\"line-height: 1.4\">.&nbsp;This&nbsp;looses precision but I have found that it usually has little effect on predictions.</span></span></li>\n<li><span style=\"font-size: 16.3636360168457px; line-height: 1.4;\">It finally converts columns to pandas sparse format (if&nbsp;to_sparse=True). &nbsp;However, this is false by default as pandas sparse columns are pretty nasty and break lots of things.</span></li>\n</ul>\n\n<p>All these extensions use my naming conventions explained here:</p>\n<p><a href=\"http://www.picnet.com.au/blogs/guido/post/2014/08/26/naming-conventions-in-predictive-analytics-and-machine-learning/\" target=\"_blank\">Guido's Naming Conventions</a></p>\n\n<p>So at least this&nbsp;fiasco has led to some ideas/code being shared. &nbsp;</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57692",
      "postDate": "11/10/2014 22:47:19",
      "content": "<p>@guido</p>\n<p>I'm going to have to create some sock-puppet accounts just so I can up-vote your pandas_extensions link!</p>\n<p>(j/k about the sock-puppet accounts)</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57694",
      "postDate": "11/10/2014 22:58:40",
      "content": "<p>[quote=B Yang;57686]</p>\n<p>Why bother with hashing at all ? In my view, the right way is&nbsp;to map each unique value to an incrementing integer ID:</p>\n<p style=\"padding-left: 30px\"><code>int new_id=0;<br>dictionary d;<br>for (each datum in data column) {<br>&nbsp; if (!d.contains_key(datum)) {<br>&nbsp;&nbsp;&nbsp;&nbsp; d[datum]=new_id;&nbsp;new_id++;<br>&nbsp; }<br>&nbsp; mapped_value=d[datum];<br>}<br></code></p>\n<p>This approach has the following advantages:</p>\n<ul>\n<li>Faster processing compared to non-trivial hashing.</li>\n<li>Smaller resulting dataset.</li>\n<li>Resistance to cracking.</li>\n</ul>\n<p>[/quote]</p>\n\n<p>Hashing with good hash functions is usually faster than dict lookup since dict does hashing as well and has additional random RAM access.</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57695",
      "postDate": "11/10/2014 23:01:05",
      "content": "<p>@Guido: This extension is very nice!!! I like the&nbsp;_df_engineer method which lets you define your own column types. I did something like this in R for 1 competition.</p>\n<p>I have 2 additional lossless compression methods that I sometimes use:</p>\n<p>1. Removing columns with only 1 unique value</p>\n<p>2. Removing columns with duplicate data (I work with bag of words models very often so it happens very frequently).</p>\n<p>Both are pretty aggressive.</p>\n<p>https://gist.github.com/pjankiewicz/0773ab67e3dd5a4cc623</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57717",
      "postDate": "11/11/2014 00:30:18",
      "content": "<p>[quote=Pawe&#322;;57695]</p>\n<p>1. Removing columns with only 1 unique value</p>\n<p>[/quote]</p>\n<p>Cool, but I think your get_useless_columns has a bug:</p>\n<p>line:</p>\n<p><code>for col in useless_columns</code></p>\n<p>should be:</p>\n<p><code>for col in&nbsp;data.columns:</code></p>\n<p>I will probably incorporate&nbsp;these into my compress function (if you dont object), my only concern is how fast is your&nbsp;hash_array function on large datasets, like the Avazu one?</p>",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "57724",
      "postDate": "11/11/2014 00:59:50",
      "content": "<p>[quote=Guocong Song;57694]</p>\n<p>Hashing with good hash functions is usually faster than dict lookup since dict does hashing as well and has additional random RAM access.</p>\n<p>[/quote]</p>\n<p>I was thinking of binary tree-based dictionaries. There're still random RAM access, but I think they'd be faster than algorithms like MD5, especially for small input strings like those in this dataset.</p>",
      "rawMarkdown": "",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 57411,
      "author_name": "jaymoore",
      "author_url": "",
      "post_date": "11/06/2014 16:02:30",
      "content": "<p>It could be interesting to correlate each of the levels of country with peak activity time of day, and at least infer longitude for each country...</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57424,
      "author_name": "herrahuu",
      "author_url": "",
      "post_date": "11/06/2014 17:23:44",
      "content": "<p>Here is a plot of normalized hourly click&nbsp;ratios (ie click ratio for each hour / average ratio) for each country:</p>\n<p><img src=\"http://img.techpowerup.org/141106/click_ratio763.png\" alt=\"click ratios\" width=\"400\" height=\"474\"></p>\n<p>Not exactly what I would have expected to see. There seems to be some kind of general trend and not huge variations between the countries etc.</p>\n<p>Edit: Hmm, maybe this could be just a&nbsp;consequence of the reported subsampling of the data</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57428,
      "author_name": "luyitian",
      "author_url": "",
      "post_date": "11/06/2014 18:45:41",
      "content": "<p>device_geo_country &nbsp;= 'dc634e20'</p>\n<p><img src=\"http://img.techpowerup.org/141106/dc634e20.png\" alt width=\"795\" height=\"596\"></p>\n<p>I arbitrarily select several device-geo-country and find most of them have statistics like the picture above, but the location of peak is different.</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57453,
      "author_name": "ozrobstar",
      "author_url": "",
      "post_date": "11/07/2014 02:45:32",
      "content": "<p>It's at least plausible that they are countries - ISO 3166 tabulates each recognised nation as a two character alpha, a three character alpha and a three character numeric - total 8 characters - and has a listing for around 250 nation-like entities.</p>\n<p>At the same time, it is also possible that a few countries - e.g. the USA - could be encoded at the state level. Not uncommon for online forms to request the user's country, and then request the user's state if and only they identify as from the US and/or a handful of other large countries.</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57460,
      "author_name": "mike64",
      "author_url": "",
      "post_date": "11/07/2014 10:09:39",
      "content": "<p>Hi OzRob,</p>\n<p>It really is a good idea but can not find the correspondence between the two codes!</p>\n\n<p>For example, dc634e20?</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57486,
      "author_name": "byang1",
      "author_url": "",
      "post_date": "11/07/2014 20:16:26",
      "content": "<p>Here's the top 10 countries in training data:</p>\n<p>1 13b5bfe9 India //md5('in') = &quot;13b5bfe96f3e2fe411c9f66f4a582adf&quot;<br>2 b80bb774 Indonesia<br>3 0b3b97fa United States<br>4 959848ca South Africa<br>5 1cd3c693 Pakistan<br>6 dc634e20 Brazil<br>7 c12e01f2 Saudi Arabia<br>8 795237fd Iraq<br>9 dcf0d7d2 Korea, Republic Of<br>10 dd07de85 Peru</p>\n\n<p>Now, let's go crack the other columns :)</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57492,
      "author_name": "derekzh",
      "author_url": "",
      "post_date": "11/07/2014 22:34:02",
      "content": "<p>B Yang: it is amazing that you are decoding the top country - very curious about how you managed to do so if you don't mind sharing the technique :)</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57493,
      "author_name": "nissanpow",
      "author_url": "",
      "post_date": "11/07/2014 22:51:23",
      "content": "<p>[quote=DerekZH;57492]</p>\n<p>B Yang: it is amazing that you are decoding the top country - very curious about how you managed to do so if you don't mind sharing the technique :)</p>\n<p>[/quote]</p>\n\n<p>He's using the first 8 chars from the md5 hash (as stated in the comment from&nbsp;line 1).</p>\n<p>MD5 (&quot;in&quot;) = 13b5bfe96f3e2fe411c9f66f4a582adf<br>MD5 (&quot;id&quot;) = b80bb7740288fda1f201890375a60c8f<br>MD5 (&quot;us&quot;) = 0b3b97fa66886c5688ee4ae80ec0c3c2<br>MD5 (&quot;za&quot;) = 959848ca10cc8a60da818ac11523dc63<br>MD5 (&quot;pk&quot;) = 1cd3c693132f4c31b5b5e5f4c5eed6bd<br>MD5 (&quot;br&quot;) = dc634e2072827fe0b5be9a2063390544<br>MD5 (&quot;sa&quot;) = c12e01f2a13ff5587e1e9e4aedb8242d<br>MD5 (&quot;iq&quot;) = 795237fd9d107e63cd19b0db0f2fba2f<br>MD5 (&quot;kr&quot;) = dcf0d7d2cd120bf42580d43f29785dd3<br>MD5 (&quot;pe&quot;) = dd07de8561395a7c37f8fcc1752d45e1</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57494,
      "author_name": "matlab",
      "author_url": "",
      "post_date": "11/07/2014 23:38:41",
      "content": "<p>Full list</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57499,
      "author_name": "byang1",
      "author_url": "",
      "post_date": "11/08/2014 03:50:46",
      "content": "<p>[quote=Nissan Pow;57493]</p>\n<p>He's using the first 8 chars from the md5 hash (as stated in the comment from&nbsp;line 1).</p>\n<p>[/quote]</p>\n<p>Yes, you hash the likely suspects and see if the leading bytes are in the data. For example, the top 5 device_os:</p>\n<ul>\n<li>c31b3236&nbsp; android</li>\n<li>2f3f71f2&nbsp; rim os</li>\n<li>990c0803&nbsp; windows phone os</li>\n<li>9e304d4e&nbsp; ios</li>\n<li>08145b8c&nbsp; symbian os</li>\n</ul>\n<p>And the top 10 device_make:</p>\n<ul>\n<li>fe546279&nbsp; samsung</li>\n<li>3d517f89</li>\n<li>a608b9c4&nbsp; lg</li>\n<li>026af9dc&nbsp; micromax</li>\n<li>33561003&nbsp; sony</li>\n<li>0c23a8bf&nbsp; nokia</li>\n<li>c1aafc7e&nbsp; huawei</li>\n<li>36dfa7ba&nbsp; rim</li>\n<li>4aab4dc9&nbsp; htc</li>\n<li>f3c0fa6b&nbsp; alcatel</li>\n</ul>\n<p>I wonder what the #2 device_make is, I suspect it's something like '-unknown-'. You can go to this web site:</p>\n<p>&nbsp;&nbsp;&nbsp; http://www.md5hashgenerator.com/index.php</p>\n<p>enter your guess and click on &quot;Generate MD5 Hash&quot;.</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57552,
      "author_name": "iamivo",
      "author_url": "",
      "post_date": "11/09/2014 12:37:24",
      "content": "<p>How can one IP have two DEVICE_GEO_COUNTRY values associated with it?</p>\n<p>For eg. c1b8122b DEVICE_IP&nbsp;has&nbsp;b80bb774 and&nbsp;0b3b97fa.</p>\n<p>Cheers!</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57591,
      "author_name": "danielhutty",
      "author_url": "",
      "post_date": "11/10/2014 11:46:18",
      "content": "<p>I would suspect that the owner of that phone has been in more than one country during the time period covered by the dataset. Whenever I travel I spend a fair amount of time messing around on my phone while waiting in airports, both while waiting for departure and waiting to get through arrivals - i.e. in 2 countries! I usually have data turned off when abroad due to roaming costs, but guess not everyone does so.</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57607,
      "author_name": "iamivo",
      "author_url": "",
      "post_date": "11/10/2014 14:54:27",
      "content": "<p>I see, but the IP of your phone is differnet in Paris and London, the geolocation is different. The question is how can the same&nbsp;IP have two different geolocations.</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57613,
      "author_name": "alexxanderlarko",
      "author_url": "",
      "post_date": "11/10/2014 16:00:21",
      "content": "<p>ivo@</p>\n<p>ivo wrote:</p>\n<p>The question is how can the same IP have two different geolocations.</p>\n<p>_________________________________________________________&nbsp;</p>\n<p>I think - this is not possible</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57622,
      "author_name": "vvarkey",
      "author_url": "",
      "post_date": "11/10/2014 17:22:08",
      "content": "<p>probably means they are going state-wise in some countries (india). and some small states in india share ip geolocations.</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57623,
      "author_name": "vvarkey",
      "author_url": "",
      "post_date": "11/10/2014 17:34:26",
      "content": "<p>on second thoughts there are 233 country codes and 232 values in the file. i'm guessing they are excluding only china.</p>\n<p>https://en.wikipedia.org/wiki/List_of_countries_by_IPv4_address_allocation</p>\n<p>there are 19 countries with 0 IPs. these probably use IP from nearby countries.</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57650,
      "author_name": "fchollet",
      "author_url": "",
      "post_date": "11/10/2014 19:26:44",
      "content": "<p>Given the initial data debacle, I was fully expecting something like this. Seriously guys, you did not salt your hashes? Did you&nbsp;expect nobody would try using common hashes on simple fields to deanonymize the data? Like it has happened every single time unsalted hashes have been used in a competition? Guys.</p>\n<p>In case you're wondering, the reason this is problematic from a privacy perspective, is that by brute-forcing the device_ip column (by hashing a few billion IPs that have been active recently and matching the hashes with the Avazu data) and the&nbsp;site_domain column (by hashing the Alexa top 1M website domains and matching them against the Avazu data), you get access to the web histories of a few hundred thousand people (assuming a reasonable brute-forcing success rate), all personally identifiable. And that's bad. &nbsp;</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57686,
      "author_name": "byang1",
      "author_url": "",
      "post_date": "11/10/2014 21:55:19",
      "content": "<p>Why bother with hashing at all ? In my view, the right way is&nbsp;to map each unique value to an incrementing integer ID:</p>\n<p style=\"padding-left: 30px\"><code>int new_id=0;<br>dictionary d;<br>for (each datum in data column) {<br>&nbsp; if (!d.contains_key(datum)) {<br>&nbsp;&nbsp;&nbsp;&nbsp; d[datum]=new_id;&nbsp;new_id++;<br>&nbsp; }<br>&nbsp; mapped_value=d[datum];<br>}<br></code></p>\n<p>This approach has the following advantages:</p>\n<ul>\n<li>Faster processing compared to non-trivial hashing.</li>\n<li>Smaller resulting dataset.</li>\n<li>Resistance to cracking.</li>\n</ul>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57687,
      "author_name": "domcastro",
      "author_url": "",
      "post_date": "11/10/2014 22:03:32",
      "content": "<p>[quote=B Yang;57686]</p>\n<p>Why bother with hashing at all ? In my view, the right way is&nbsp;to map each unique value to an incrementing integer ID:</p>\n<p style=\"padding-left: 30px\"><code>int new_id=0;<br>dictionary d;<br>for (each datum in data column) {<br>&nbsp; if (!d.contains_key(datum)) {<br>&nbsp;&nbsp;&nbsp;&nbsp; d[datum]=new_id;&nbsp;new_id++;<br>&nbsp; }<br>&nbsp; mapped_value=d[datum];<br>}<br></code></p>\n<p>This approach has the following advantages:</p>\n<ul>\n<li>Faster processing compared to non-trivial hashing.</li>\n<li>Smaller resulting dataset.</li>\n<li>Resistance to cracking.</li>\n</ul>\n<p>[/quote]</p>\n\n<p>Agreed. I usually do this for long hashes anyway as it frees up more memory</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57688,
      "author_name": "paweljankiewicz",
      "author_url": "",
      "post_date": "11/10/2014 22:03:39",
      "content": "<p>@B Yang: Actually this how I first processed this dataset. I sorted ids in decreasing order (so 0 value is the most frequent). It reduced the size of the data by 50%. I don't know if it helps someone but I'm attaching the script to do this. The list of columns is wrong (they changed the column labels) and I don't have the correct list.</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57690,
      "author_name": "guidotapia",
      "author_url": "",
      "post_date": "11/10/2014 22:43:34",
      "content": "<p>[quote=Pawe&#322;;57688]</p>\n<p>@B Yang: Actually this how I first processed this dataset. I sorted ids in decreasing order (so 0 value is the most frequent). It reduced the size of the data by 50%. ...</p>\n<p>[/quote]</p>\n<p>I do something similar see:</p>\n<p><a href=\"https://github.com/gatapia/py_ml_utils/blob/master/pandas_extensions.py\" target=\"_blank\">pandas_extensions.py</a></p>\n\n<p>These are pandas extension methods, it includes a:</p>\n<p><code>DataFrame.compress(aggresiveness=0,to_sparse=False)</code></p>\n<p>method that reduces size of data by 60-85% it does the following:</p>\n<ul>\n<li><span style=\"font-size: 16.3636360168457px; line-height: 1.4;\">Sorts categoricals by frequency and converts to ints with highest freq first</span></li>\n<li><span style=\"font-size: 16.3636360168457px; line-height: 1.4;\">Uses lowest possible dtype for each column (instead of 64 bit floats by default I can get some columns down to 8bits)</span></li>\n<li><span style=\"font-size: medium\"><span style=\"line-height: 1.4\">It has an&nbsp;</span></span><span style=\"line-height: 20.8264446258545px\">aggressiveness</span><span style=\"font-size: medium\"><span style=\"line-height: 1.4\">&nbsp;attribute which will convert float64 -&gt; 32 or 16 bit depending on&nbsp;</span>aggressiveness<span style=\"line-height: 1.4\">.&nbsp;This&nbsp;looses precision but I have found that it usually has little effect on predictions.</span></span></li>\n<li><span style=\"font-size: 16.3636360168457px; line-height: 1.4;\">It finally converts columns to pandas sparse format (if&nbsp;to_sparse=True). &nbsp;However, this is false by default as pandas sparse columns are pretty nasty and break lots of things.</span></li>\n</ul>\n\n<p>All these extensions use my naming conventions explained here:</p>\n<p><a href=\"http://www.picnet.com.au/blogs/guido/post/2014/08/26/naming-conventions-in-predictive-analytics-and-machine-learning/\" target=\"_blank\">Guido's Naming Conventions</a></p>\n\n<p>So at least this&nbsp;fiasco has led to some ideas/code being shared. &nbsp;</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57692,
      "author_name": "inversion",
      "author_url": "",
      "post_date": "11/10/2014 22:47:19",
      "content": "<p>@guido</p>\n<p>I'm going to have to create some sock-puppet accounts just so I can up-vote your pandas_extensions link!</p>\n<p>(j/k about the sock-puppet accounts)</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57694,
      "author_name": "songgc",
      "author_url": "",
      "post_date": "11/10/2014 22:58:40",
      "content": "<p>[quote=B Yang;57686]</p>\n<p>Why bother with hashing at all ? In my view, the right way is&nbsp;to map each unique value to an incrementing integer ID:</p>\n<p style=\"padding-left: 30px\"><code>int new_id=0;<br>dictionary d;<br>for (each datum in data column) {<br>&nbsp; if (!d.contains_key(datum)) {<br>&nbsp;&nbsp;&nbsp;&nbsp; d[datum]=new_id;&nbsp;new_id++;<br>&nbsp; }<br>&nbsp; mapped_value=d[datum];<br>}<br></code></p>\n<p>This approach has the following advantages:</p>\n<ul>\n<li>Faster processing compared to non-trivial hashing.</li>\n<li>Smaller resulting dataset.</li>\n<li>Resistance to cracking.</li>\n</ul>\n<p>[/quote]</p>\n\n<p>Hashing with good hash functions is usually faster than dict lookup since dict does hashing as well and has additional random RAM access.</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57695,
      "author_name": "paweljankiewicz",
      "author_url": "",
      "post_date": "11/10/2014 23:01:05",
      "content": "<p>@Guido: This extension is very nice!!! I like the&nbsp;_df_engineer method which lets you define your own column types. I did something like this in R for 1 competition.</p>\n<p>I have 2 additional lossless compression methods that I sometimes use:</p>\n<p>1. Removing columns with only 1 unique value</p>\n<p>2. Removing columns with duplicate data (I work with bag of words models very often so it happens very frequently).</p>\n<p>Both are pretty aggressive.</p>\n<p>https://gist.github.com/pjankiewicz/0773ab67e3dd5a4cc623</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57717,
      "author_name": "guidotapia",
      "author_url": "",
      "post_date": "11/11/2014 00:30:18",
      "content": "<p>[quote=Pawe&#322;;57695]</p>\n<p>1. Removing columns with only 1 unique value</p>\n<p>[/quote]</p>\n<p>Cool, but I think your get_useless_columns has a bug:</p>\n<p>line:</p>\n<p><code>for col in useless_columns</code></p>\n<p>should be:</p>\n<p><code>for col in&nbsp;data.columns:</code></p>\n<p>I will probably incorporate&nbsp;these into my compress function (if you dont object), my only concern is how fast is your&nbsp;hash_array function on large datasets, like the Avazu one?</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 57724,
      "author_name": "byang1",
      "author_url": "",
      "post_date": "11/11/2014 00:59:50",
      "content": "<p>[quote=Guocong Song;57694]</p>\n<p>Hashing with good hash functions is usually faster than dict lookup since dict does hashing as well and has additional random RAM access.</p>\n<p>[/quote]</p>\n<p>I was thinking of binary tree-based dictionaries. There're still random RAM access, but I think they'd be faster than algorithms like MD5, especially for small input strings like those in this dataset.</p>",
      "votes": null,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "57405": "",
    "57411": "",
    "57424": "",
    "57428": "",
    "57453": "",
    "57460": "",
    "57486": "",
    "57492": "",
    "57493": "",
    "57494": "",
    "57499": "",
    "57552": "",
    "57591": "",
    "57607": "",
    "57613": "",
    "57622": "",
    "57623": "",
    "57650": "",
    "57686": "",
    "57687": "",
    "57688": "",
    "57690": "",
    "57692": "",
    "57694": "",
    "57695": "",
    "57717": "",
    "57724": ""
  },
  "source": "meta"
}