Skip to content

Instantly share code, notes, and snippets.

@mlopatka
Created October 13, 2016 17:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mlopatka/55ae54a19ca49bdd3a22ddf0b1350649 to your computer and use it in GitHub Desktop.
Save mlopatka/55ae54a19ca49bdd3a22ddf0b1350649 to your computer and use it in GitHub Desktop.
score_dist_ranker
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Unable to parse whitelist (/home/hadoop/anaconda2/lib/python2.7/site-packages/moztelemetry/histogram-whitelists.json). Assuming all histograms are acceptable.\n",
"Populating the interactive namespace from numpy and matplotlib\n"
]
}
],
"source": [
"import numpy as np\n",
"import math\n",
"\n",
"from pyspark.sql import SQLContext, Row\n",
"from moztelemetry import get_pings, get_pings_properties, get_one_ping_per_client, get_clients_history, get_records\n",
"\n",
"import numpy as np\n",
"import matplotlib.mlab as mlab\n",
"import matplotlib.pyplot as plt\n",
"\n",
"import scipy.stats\n",
"import scipy.optimize\n",
"from scipy.stats.stats import pearsonr\n",
"import scipy.spatial.distance as spdist\n",
"\n",
"import urllib2, json\n",
"\n",
"%pylab inline\n",
"matplotlib.rcParams['figure.figsize'] = (12.0, 6.0)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"RAND_SEED = 422950748\n",
"ADDON_EXCLUSION_LIST = ['loop@mozilla.org', 'firefox@getpocket.com', 'e10srollout@mozilla.org', 'firefox-hotfix@mozilla.org']\n",
"#mozColours\n",
"db = [0.00, 0.13, 0.28]\n",
"lb = [0.00, 0.59, 0.87]\n",
"lo = [1.00, 0.58, 0.00]\n",
"do = [0.90, 0.38, 0.00]"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 1.63 s, sys: 120 ms, total: 1.75 s\n",
"Wall time: 1min 19s\n"
]
}
],
"source": [
"%%time\n",
"freshPings_addon_DF = sqlContext.sql(\"SELECT * FROM longitudinal\")\\\n",
" .where(\"active_addons IS NOT null and size(active_addons[0]) > 0\")\\\n",
" .where(\"size(active_addons) > 1\")\\\n",
" .where(\"size(active_addons) < 999\")\\\n",
" .where(\"build IS NOT null AND build[0].application_name = 'Firefox'\")\\\n",
" .selectExpr(\"client_id as client_id\", \"active_addons[0] as active_addons\")\n",
"\n",
"# .where(\"size(active_addons) > 1\")\\\n",
"# this is a temporayr hack to get aroudn the telemetry bug!!!! and should be removed when the issue is resolved.\n",
"\n",
"freshPings_cat_DF = sqlContext.sql(\"SELECT * FROM longitudinal\")\\\n",
" .where(\"active_addons IS NOT null and size(active_addons[0]) > 0\")\\\n",
" .where(\"size(active_addons) > 1\")\\\n",
" .where(\"build IS NOT null AND build[0].application_name = 'Firefox'\")\\\n",
" .selectExpr(\"client_id as client_id\", \"geo_country[0] as geo_country\",\\\n",
" \"os as os\",\\\n",
" \"system[0].memory_mb as sys_mem\",\\\n",
" \"system[0].virtual_max_mb as virt_mem\",\\\n",
" \"theme[0].id as theme\",\\\n",
" #\"flash_version[0] as flash\",\\\n",
" \"system_gfx[0].monitors.screen_width as scrnWd\",\\\n",
" #\"number_of_profiles as prof_num\",\\\n",
" \"settings[0].e10s_enabled as e10_bool\",\\\n",
" \"settings[0].telemetry_enabled as telemetry_bool\",\\\n",
" \"settings[0].default_search_engine_data.name as default_search\",\\\n",
" \"settings[0].locale as loc\",\\\n",
" \"settings[0].update.channel as channel\"\\\n",
" )\n",
"\n",
"# Thanks to Alessio, for being a BOSS\n",
"\n",
"\"\"\"\n",
"freshPings_con_DF = sqlContext.sql(\"SELECT * FROM longitudinal\")\\\n",
" .where(\"active_addons IS NOT null\")\\\n",
" .where(\"build IS NOT null AND build[0].application_name = 'Firefox'\")\\\n",
" .selectExpr(\"client_id as client_id\", \"session_length[0] as session_length\",\\\n",
" \"paint_build_displaylist_time[0] as paint_time\", \"predictor_wait_time[0] as predictor_wait_time\",\\\n",
" \"html_background_reflow_ms_2[0] as reflow_ms\", \"telemetry_memory_reporter_ms[0] as tele_rep_time\",\\\n",
" \"image_decode_latency_us[0] as im_decode_latency\", \"http_subitem_open_latency_time[0] as op_latent\"\\\n",
" )\n",
"\"\"\"\n",
"\n",
"subset_addon_rdd = freshPings_addon_DF.sample(False, 0.1, RAND_SEED).rdd.cache()\n",
"subset_addon_tok_rdd = subset_addon_rdd.map(lambda p: (p['client_id'], p['active_addons'].keys())).cache()\n",
"\n",
"# to filter by client_id\n",
"def isinSet(p):\n",
" return p in valid_ID_in_addon_Set # this must be broadcast\n",
"\n",
"def filterSystemAddons(p, ADDON_EXCLUSION_LIST):\n",
" return [x for x in p if x not in ADDON_EXCLUSION_LIST]\n",
" \n",
"subset_addon_tok_filtered_rdd = subset_addon_tok_rdd.map(lambda p: (p[0], filterSystemAddons(p[1], ADDON_EXCLUSION_LIST))).filter(lambda p: len(p[1])>1).cache()\n",
"\n",
"valid_ID_in_addon_Set = set(subset_addon_tok_filtered_rdd.map(lambda p: p[0]).collect())#set of valid target ids that were randomly chosen for addons\n",
"sc.broadcast(valid_ID_in_addon_Set)\n",
"\n",
"subset_cat_rdd = freshPings_cat_DF.rdd.filter(lambda p: isinSet(p[0])).cache()"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[Row(client_id=u'ffff00f7-3baf-4b2f-9697-3fc1aecfd6d2', geo_country=u'PL', os=u'Windows_NT', sys_mem=6092, virt_mem=None, theme=u'{972ce4c6-7e08-4474-a285-3208198ce6fd}', scrnWd=[1600], e10_bool=True, telemetry_bool=False, default_search=u'Google', loc=u'pl', channel=u'release')]"
]
},
"execution_count": 67,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"freshPings_cat_DF.take(1)"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"158840\n",
"158840\n"
]
}
],
"source": [
"print subset_cat_rdd.count()\n",
"print subset_addon_tok_filtered_rdd.count()\n",
"#subset_addon_tok_filtered_rdd.take(100)"
]
},
{
"cell_type": "code",
"execution_count": 186,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 0 ns, sys: 0 ns, total: 0 ns\n",
"Wall time: 30 µs\n"
]
}
],
"source": [
"%%time\n",
"# implement some standard nlp functions to work with addons\n",
"\n",
"def addon_frequency(add_on_list):\n",
" # we can cheat a bit here becasue we know the tf (token frequency is always 1/number_of_elements)\n",
" addict = dict()\n",
" l = len(add_on_list)\n",
" for i in add_on_list:\n",
" addict[i] = float(1)/l # quack quack!\n",
" return addict # the dictionary of addon names (keys) to frequency (value)\n",
"\n",
"def population_frequency(corpusRDD):\n",
" total_pings = corpusRDD.count()\n",
" addons_intf = corpusRDD.flatMap(lambda p: list(set(p[1]))) # in principal the <list(set())> is unnecessary but lets be safe!\n",
" addonCountPairRDD = addons_intf.map(lambda p: (p,1)) # creating a pairRDD with integer 1's all over the values\n",
" addonSumPairRDD = addonCountPairRDD.reduceByKey(add)\n",
" population_frequency_addons = addonSumPairRDD.map(lambda p: (p[0], float(total_pings)/p[1])) #dividing the lexicon count by the frequency\n",
" return population_frequency_addons\n",
"\n",
"def addonRarity(addons_freq): \n",
" # corpusIDFsBroadcast MUST be a broadcast variable or everything breaks down!\n",
" # it must be a dict of {addon_name, frequency})\n",
" addon_dict_intf = dict()\n",
" \n",
" t = float(1)/len(addons_freq)#if the possibility of duplicates exists then: <float(1)> becomes <float(addons_frequency.count(i))/len(addons_frequency) and goes inside the loop\n",
" for i in addons_freq:\n",
" addon_dict_intf[i] = t*corpus_addons_IDFs_Broadcast.get(i,1)\n",
" return addon_dict_intf\n",
"\n",
"def catVarRarity(cat_freq): \n",
" # corpusIDFsBroadcast MUST be a broadcast variable or everything breaks down!\n",
" # it must be a dict of {addon_name, frequency})\n",
" dict_intf = dict()\n",
" \n",
" t = float(1)/len(addons_freq)#if the possibility of duplicates exists then: <float(1)> becomes <float(addons_frequency.count(i))/len(addons_frequency) and goes inside the loop\n",
" for i in cat_freq:\n",
" dict_intf[i] = t*corpusCatIDFsBroadcast.get(i,1)\n",
" return addon_dict_intf\n",
"\n",
"def convertKeyCombinedIDs(p):# need to combine the keys ping_ids into a concatenated string for the comparison \n",
" # this will allow quick exploration of the \n",
" source_1_id = str(p[0][0])\n",
" source_2_id = str(p[0][1])\n",
" similarity_score = p[1]\n",
" return (source_1_id + ' ' + source_2_id, similarity_score)\n",
" \n",
"def count_entities(p):\n",
" tally_counter = p.map(lambda q: len(q[1])).reduce(add)\n",
" return tally_counter\n",
"\n",
"def exclude_empty_entities(p):\n",
" return bool(p[1])#how pythonic \n",
"\n",
"def addonID2addonName(a):\n",
" return addonIdsToNames_broadcast[a]\n",
"\n",
"def tokenize_catVar(p):\n",
" names = p.asDict()\n",
" del names['client_id']\n",
" cat_list = []\n",
" for i in names:\n",
" staging_string = safe_unicode(i) + '_' + safe_unicode(names[i])\n",
" cat_list.append(staging_string)\n",
" return (p[0], cat_list)\n",
"\n",
"def dotprod(x1,x2):\n",
" idx = list(x1.viewkeys() & x2.viewkeys())\n",
" dotProd = 0\n",
" for i in idx:\n",
" dotProd += x1.get(i,1)*x2.get(i,1)\n",
" return dotProd\n",
"\n",
"def norm(x):\n",
" normVal = 0\n",
" idx = list(x.viewkeys())\n",
" for i in idx:\n",
" normVal += (x.get(i,1)*x.get(i,1))\n",
" return math.sqrt(normVal)\n",
"\n",
"def cosSim(x1,x2):\n",
" return dotprod(x1,x2)/norm(x1)/norm(x2)\n",
"\n",
"def cosSimHelper(list_1,list_2):\n",
" w1 = addonRarity(addon_frequency(list_1))\n",
" w2 = addonRarity(addon_frequency(list_2))\n",
" return cosSim(w1,w2) \n",
"\n",
"def computeCosSim(pair_record):\n",
" #requires the corpusIDFs to be broadcast!\n",
" source_1 = pair_record[0]\n",
" source_2 = pair_record[1]\n",
" ping_id_1 = source_1[0]\n",
" ping_id_2 = source_2[0]\n",
" value_1 = source_1[1]\n",
" value_2 = source_2[1]\n",
" cs = cosSimHelper(value_1,value_2)\n",
" return ((ping_id_1, ping_id_2),cs)\n",
"\n",
"def computeOtherSim(pair_record):\n",
" #requires the corpusIDFs to be broadcast!\n",
" source_1 = pair_record[0]\n",
" source_2 = pair_record[1]\n",
" ping_id_1 = source_1[0]\n",
" ping_id_2 = source_2[0]\n",
" value_1 = source_1[1]\n",
" value_2 = source_2[1]\n",
" cs = otherSimHelper(value_1,value_2)\n",
" return ((ping_id_1, ping_id_2),cs)\n",
"\n",
"def otherSimHelper(list_1,list_2):\n",
" w1 = catVarRarity(addon_frequency(list_1))\n",
" w2 = catVarRarity(addon_frequency(list_2))\n",
" return spdist.correlation(w1.values(), w2.values()) \n",
"\n",
"def generate_nonCartesian_pairWiseComparison_RDD(rddq):\n",
" rdd1,rdd2 = rddq.randomSplit([0.5,0.5], RAND_SEED)\n",
" rdd1b = rdd1.zipWithIndex().map(lambda p: (p[1],p[0]))\n",
" rdd2b = rdd2.zipWithIndex().map(lambda p: (p[1],p[0]))\n",
" rddc = rdd1b.join(rdd2b).map(lambda p: p[1])\n",
" return rddc\n",
"\n",
"def safe_unicode(obj, *args):\n",
" try:\n",
" return str(obj, *args)\n",
" except UnicodeEncodeError: \n",
" return unicode('ascii_text_fail_sauce')\n",
"\n",
"def catVarRarity(addons_freq): \n",
" # corpusIDFsBroadcast MUST be a broadcast variable or everything breaks down!\n",
" # it must be a dict of {addon_name, frequency})\n",
" addon_dict_intf = dict()\n",
" \n",
" t = float(1)/len(addons_freq)#if the possibility of duplicates exists then: <float(1)> becomes <float(addons_frequency.count(i))/len(addons_frequency) and goes inside the loop\n",
" for i in addons_freq:\n",
" addon_dict_intf[i] = t*corpusCatIDFsBroadcast.get(i,1)\n",
" return addon_dict_intf"
]
},
{
"cell_type": "code",
"execution_count": 150,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"158840 records parsed including 616529 addon installations\n",
"CPU times: user 352 ms, sys: 72 ms, total: 424 ms\n",
"Wall time: 2.52 s\n"
]
}
],
"source": [
"%%time\n",
"\n",
"recCNT = subset_addon_tok_filtered_rdd.count()\n",
"addonCNT = count_entities(subset_addon_tok_filtered_rdd)\n",
"\n",
"print str(recCNT) + ' records parsed including ' + str(addonCNT) +' addon installations' "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### We will borrow many concepts from NLP here. but we have it easy, becasue our lexicon is only the total number of possible add-ons, so calculating IDF (inverse document frequency) and TF (token frequency) we can convert our add-ons list to a numerical vector representing each addon list as a vector of numerical weights favouring rare add-ons (in pairwise comparisons between users)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### This will take a long time! we use the superset that our small sample was drawn from to ensure that the set esclusion is empty. Then calculate the frequency of addons globally within the freshest part of the longitudinal corpus, once again excluding pings wiht no add-ons for now."
]
},
{
"cell_type": "code",
"execution_count": 151,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 740 ms, sys: 256 ms, total: 996 ms\n",
"Wall time: 2min 41s\n"
]
}
],
"source": [
"%%time\n",
"corpusTokenizedRDD = freshPings_addon_DF.map(lambda p: (p['client_id'], p['active_addons'].keys()))\n",
"corpusIDFs = population_frequency(corpusTokenizedRDD)\n",
"## DISCUSSION POINT: should we include the subsample in the corpus:\n",
"# option 1: no, but then filter out addons we have not seen yet in the corpus, from the sample\n",
"# option 2: yes leave the corpus as the super set and risk overfitting\n",
"corpus_addons_IDFs_Broadcast = corpusIDFs.collectAsMap()\n",
"sc.broadcast(corpus_addons_IDFs_Broadcast) # this is really important, otherwise we are sending this to each worker FOR EACH partition!!!\n",
"\n",
"tokenized_catVars_corpus = subset_cat_rdd.map(lambda p: tokenize_catVar(p)).filter(lambda p: exclude_empty_entities(p)).cache()\n",
"#cnt = tokenized_catVars_corpus.count()\n",
"corpusCatIDFs = population_frequency(tokenized_catVars_corpus) # idfs of the keys in the pair rdd\n",
"corpusCatIDFsBroadcast = corpusCatIDFs.collectAsMap() \n",
"sc.broadcast(corpusCatIDFsBroadcast)#broadcast the idfs (this should be small)"
]
},
{
"cell_type": "code",
"execution_count": 152,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 524 ms, sys: 0 ns, total: 524 ms\n",
"Wall time: 1.7 s\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f9c46fcead0>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%time\n",
"vals_idf = corpusIDFs.collect() # maybe we need to subsample!\n",
"temp = []\n",
"for i in vals_idf:\n",
" temp.append(i[1]) #store it on the client machine (locally) as a list\n",
"# plot with plotly \n",
"n, bins, patches = plt.hist(temp, 150, normed=1, facecolor=db, alpha=0.85)\n",
"plt.xlabel('document TF-IDF values observed \\n <- occurs in most users (less informative) | occurs rarely relative to corpus (more informative) ->')\n",
"plt.ylabel('Frequency (normalized)')\n",
"plt.title('token frequency for the entire addons corpus')\n",
"plt.ylim(0, 0.000005)\n",
"plt.xlim(0,5e6)"
]
},
{
"cell_type": "code",
"execution_count": 153,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Most frequently installed add-ons (system addons not filtered): [(u'e10srollout@mozilla.org', 1.2488653085977086), (u'firefox@getpocket.com', 1.2499676031565732), (u'loop@mozilla.org', 1.6162242254433212), (u'webcompat@mozilla.org', 3.528180720788854), (u'firefox-hotfix@mozilla.org', 4.229807166713308), (u'{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}', 9.624856177047047), (u'{82AF8DCA-6DE9-405D-BD5E-43525BDAD38A}', 18.203081736938074), (u'cpmanager@mozillaonline.com', 24.14173616225146), (u'cehomepage@mozillaonline.com', 24.40709402526322), (u'tabtweak@mozillaonline.com', 25.139578745563355), (u'easyscreenshot@mozillaonline.com', 25.34417589076302), (u'commonfix@mozillaonline.com', 26.342349728259393), (u'coba@mozilla.com.cn', 26.741918415265307), (u'wx-assistant@mozillaonline.com', 27.194279564829916), (u'ubufox@ubuntu.com', 30.40630836143038), (u'{b9db16a4-6edc-47ec-a1f4-b86292ed211d}', 40.94806181268831), (u'wrc@avast.com', 44.12423834555012), (u'{4ED1F68A-5463-4931-9384-8FFF5ED91D92}', 45.32794895270838), (u'websensehelper@mozilla.org', 56.3116643454039), (u'mozilla_cc2@internetdownloadmanager.com', 60.99533591471387)]\n",
"\n",
"Least popular installed add-ons: [(u'{7b60695d-93dd-b8bb-df00-07175d4943c4}', 4851813.0), (u'{37cf493a-4e65-43e0-9f19-5f53f08c158c}', 4851813.0), (u'q7@j.edu', 4851813.0), (u'{950FBDF2-65C9-4F52-8B28-0D603AB4D363}', 4851813.0), (u'{27dc79cb-1da2-4f17-b6c1-234a8e734e30}', 4851813.0), (u'{776C1E65-949E-40A3-8F05-469ADE0A22A5}', 4851813.0), (u'lhaLSke3r@w.com', 4851813.0), (u'{1017a57d-4ef6-4028-b652-b305eec9a01f}', 4851813.0), (u'{67568404-43ba-499e-201e-ff44c1809b00}', 4851813.0), (u'f@CUUx0H.com', 4851813.0), (u'{7ea51898-cd2f-c610-6a8c-9862b4ab2f3f}', 4851813.0), (u'{262e4ab9-169e-320e-ca6c-4b85509f027e}', 4851813.0), (u'{3B67A3E3-1E19-E1C3-3D6E-16ECB455F7E9}', 4851813.0), (u'lQ2@ZG.org', 4851813.0), (u'nqayg@rxkopkub.co.uk', 4851813.0), (u'{3048f9e7-3731-4484-93ce-291550662c52}', 4851813.0), (u'Gr@2ELqYI61.com', 4851813.0), (u'{dbbd3679-b08d-4c12-acba-69ba6c11b79e}', 4851813.0), (u'{a226f984-d019-48b6-926d-e68ee3ace062}', 4851813.0), (u'uiuz4@ammebng.net', 4851813.0)]\n",
"CPU times: user 0 ns, sys: 0 ns, total: 0 ns\n",
"Wall time: 2.33 s\n"
]
}
],
"source": [
"%%time\n",
"# here is a nice place to exmaine the most and least frequent addons\n",
"mostFrequent_addons = corpusIDFs.takeOrdered(20, lambda p: p[1])\n",
"print 'Most frequently installed add-ons (system addons not filtered): ' + str(mostFrequent_addons) + '\\n'\n",
"\n",
"leastFrequent_addons = corpusIDFs.takeOrdered(20, lambda p: -1*p[1])\n",
"print 'Least popular installed add-ons: ' + str(leastFrequent_addons)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Low popularity (rare) addons may still be very useful in recomending addons for some users. I.e. if two users have a similar profile in terms of rare characteristics, that is weighted more heavily than if they are similar in terms of very common characteristics. "
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"### OK, now we need to compare pairwise similarity between addon weight vector\n"
]
},
{
"cell_type": "code",
"execution_count": 154,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"79393\n",
"CPU times: user 660 ms, sys: 120 ms, total: 780 ms\n",
"Wall time: 7.14 s\n"
]
}
],
"source": [
"%%time\n",
"crossSmall_addons = generate_nonCartesian_pairWiseComparison_RDD(subset_addon_tok_filtered_rdd)\n",
"print crossSmall_addons.count()"
]
},
{
"cell_type": "code",
"execution_count": 155,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[((u'fed41971-a93b-436b-94e0-ae87d10716cd', u'fb9f8c86-29ad-4443-98a1-563d058b3d7a'), 0.0), ((u'6fec054c-be95-43f4-8172-f1deb57dceb3', u'fbee6cd8-f1b5-476d-b065-ea70b9f2a78b'), 0.0), ((u'd345aada-d5c2-4349-905f-322ea7b2383a', u'a4f59b59-328b-44b7-b015-20b4a4e440a6'), 0.0), ((u'00842a3f-cf8a-454d-8fd0-d7a7cfbce44d', u'7b58501b-11f9-492a-b073-27e41d6c638a'), 0.0), ((u'95c28af4-4feb-4e03-beb8-dd1cf2847f40', u'85049883-0e9a-49f0-bb32-b6999755674f'), 0.0), ((u'e913a1bd-3090-487b-848f-71d514cd3c7e', u'75d24387-1b75-478f-b610-60dddbc064fd'), 0.0031155962707928235), ((u'f1e2280e-4811-44ec-81b2-135a214a0fad', u'3f693407-3e64-418a-be31-d50a8232f47c'), 0.02304695266710842), ((u'a051fc62-02b0-4821-85bd-37ab41e75997', u'9e59a25d-3425-4332-ba67-1977abe002d4'), 0.0), ((u'4e6776f3-fc13-4b24-89a9-8205db776c3e', u'3d73bc0d-a7f4-4f65-bd27-bfb5afa7ceea'), 0.0), ((u'db388645-e886-4275-b93c-0943f4242d92', u'7fa6d64c-7de7-4746-98e5-67205b3702a9'), 0.0)]\n",
"CPU times: user 552 ms, sys: 0 ns, total: 552 ms\n",
"Wall time: 660 ms\n"
]
}
],
"source": [
"%%time\n",
"sims_addon = crossSmall_addons.map(lambda p: computeCosSim(p)).cache()\n",
"print sims_addon.take(10)"
]
},
{
"cell_type": "code",
"execution_count": 156,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(0, 1)"
]
},
"execution_count": 156,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\nSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ\n6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnq\nyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerI\nZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shk\nWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRa\nkiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqS\nJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIk\nSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ\n6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSeporMl0kgOSLE1yes+wvZJcmOTk9t+TxxmDJEmS\nNC7jbpk+EHjSgOEfraod2n8/GHMMkiRJ0liMNZmuquOAKweMyjiXK0mSJM2Gueoz/YYkpyb5fJKN\n5igGSZIkaZXMRTK9H3DPqnowcAnw0TmIQZIkSVpl68z2Aqvqsp6P+wNHTDb9h469HIDrbyquvva2\nY4xMkiRJa4rFixezePHiVS4nVbXq0Uy2gGRr4IiqemD7+S5VdUn791uAh1XVLkPmraV7bAvAsuuX\ns+tR4ZdnnD3WeCVJkrTmSUJVTfu+vrG2TCc5FFgEbJLkfGAv4HFJHgzcDPwJeO04Y5AkSZLGZazJ\n9JAW5wPHuUxJkiRptvgGREmSJKkjk2lJkiSpI5NpSZIkqSOTaUmSJKkjk2lJkiSpI5NpSZIkqSOT\naUmSJKkjk2lJkiSpI5NpSZIkqSOTaUmSJKkjk2lJkiSpI5NpSZIkqSOTaUmSJKkjk2lJkiSpI5Np\nSZIkqSOTaUmSJKkjk2lJkiSpI5NpSZIkqSOTaUmSJKkjk2lJkiSpI5NpSZIkqaN1ppogyVrAg4DN\n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\n3jnvvAvYdsvNVhq2+RZ3Y/HxJ81RRJIkSVqTLahk+qblN3HcSzZeadiOh1w4R9FIkiRpTWc3D0mS\nJKkjk2lJkiSpI5NpSZIkqSOTaUmSJKkjk2lJkiSpI5NpSZIkqSOTaUmSJKkjk2lJkiSpI5NpSZIk\nqaM5ewNikj8BfwZuBm6sqofPVSySJElSF3P5OvGbgUVVdeUcxiBJkiR1NpfdPDLHy5ckSZJWyVwm\nswX8KMmJSV49h3FIkiRJncxlN49HV9XFSe5Mk1SfVVXHzWE8kiRJ0rTMWTJdVRe3/1+W5HDg4cCt\nkukPHXs5ANffVNy4vGY1RkmSJK2eFi9ezOLFi1e5nFTNfoKaZH1graq6NsntgCOB91TVkX3T1dI9\ntgVg2fXL2XH/P/GbN22zUlk7HnIVv79g6SxFLkmSpNVREqoq051vrlqmNwMOT1JtDF/qT6QlSZKk\n+W5OkumqOhd48FwsW5IkSWu2RY98CEsuunBGyprLGxAlSZKkWbfkogs57iUbrzRss30u7VSWz3mW\nJEmSOjKZliRJkjoymZYkSZI6MpmWJEmSOjKZliRJkjoymZYkSZI6MpmWJEmSOlrwz5letmwZ2265\n2S2fN9/ibiw+/qQ5jEiSJElrigWfTNfNy1d66PaOh8zM22wkSZKkqdjNQ5IkSerIZFqSJEnqyGRa\nkiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqS\nJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIk\nSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ\n6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnqyGRakiRJ6shkWpIkSerIZFqSJEnq\naJ25DmA2LHrkQ1hy0YW3fN58i7ux+PiT5jAiSZIkrQ7WiGR6yUUXctxLNr7l846HXDjJ1JIkSdJo\n7OYhSZIkdWQyLUmSJHVkMi1JkiR1ZDItSZIkdWQyLUmSJHVkMi1JkiR1ZDItSZIkdWQyLUmSJHVk\nMi1JkiR1tNq9AXHZsmVsu+VmKw27ctkyYOPBM0iSJEkdrXbJdN28fKVXhwPcb9/L5igaSZIkrc7s\n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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f9c47610310>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"vals_css = sims_addon.collect() # maybe we need to subsample!\n",
"temp2 = []\n",
"for i in vals_css:\n",
" if i[1] > 0:\n",
" temp2.append(i[1]) #store it on the client machine (locally) as a list\n",
"n, bins, patches = plt.hist(temp2, 150, normed=1, facecolor=do, alpha=0.85)\n",
"plt.xlabel('Pairwise cosine similarity in addons features')\n",
"plt.ylabel('Frequency (normalized)')\n",
"plt.title('Distribution in pairwise similarity in addons sense for 5% sample of longitudinal (excluding 0 vals)')\n",
"plt.ylim(0, 20)\n",
"plt.xlim(0,1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### it may be interesting to normalize these values by the number of add-ons in the comparison!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# OK, lets try to relate the pairwise addon similarities to something else"
]
},
{
"cell_type": "code",
"execution_count": 157,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[Row(client_id=u'fed41971-a93b-436b-94e0-ae87d10716cd', geo_country=u'VN', os=u'Windows_NT', sys_mem=4060, virt_mem=None, theme=None, scrnWd=None, e10_bool=False, telemetry_bool=True, default_search=None, loc=u'en-US', channel=u'beta')]"
]
},
"execution_count": 157,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#freshPings_cat_DF.take(3)\n",
"subset_cat_rdd.take(1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Because these are categorical variables with a (small) finite set of possible values, we can use them almost exactly the same way as we did with addon names. This we we can reuse a lot of the code."
]
},
{
"cell_type": "code",
"execution_count": 158,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[(u'fed41971-a93b-436b-94e0-ae87d10716cd', ['loc_en-US', 'sys_mem_4060', 'e10_bool_False', 'geo_country_VN', 'scrnWd_None', 'default_search_None', 'telemetry_bool_True', 'theme_None', 'virt_mem_None', 'os_Windows_NT', 'channel_beta'])]\n"
]
}
],
"source": [
"tokenized_catVars = subset_cat_rdd.map(lambda p: tokenize_catVar(p))\n",
"print tokenized_catVars.take(1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### then perform pairwise similarity comparisons and keep track of SS and SD compariosns in a list of id pairs"
]
},
{
"cell_type": "code",
"execution_count": 159,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[((u'fed41971-a93b-436b-94e0-ae87d10716cd', u'fb9f8c86-29ad-4443-98a1-563d058b3d7a'), 0.0)]\n",
"[((u'12bdad98-650c-46f3-9c53-7b22ef3670b4', u'6fef8520-4ea7-3e4e-aa3f-9e72332e1f1f'), -0.10051955521811662)]\n"
]
}
],
"source": [
"crossSmall_cats = generate_nonCartesian_pairWiseComparison_RDD(tokenized_catVars)\n",
"sims_cats = crossSmall_cats.map(lambda p: computeOtherSim(p)).cache()\n",
"print sims_addon.take(1)\n",
"print sims_cats.take(1)\n",
"#crossSmall_cats.take(1)"
]
},
{
"cell_type": "code",
"execution_count": 160,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"c = sims_addon.map(lambda p: p[0]).intersection(sims_cats.map(lambda p: p[0])).count()"
]
},
{
"cell_type": "code",
"execution_count": 161,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"79393\n"
]
}
],
"source": [
"print c"
]
},
{
"cell_type": "code",
"execution_count": 162,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 452 ms, sys: 4 ms, total: 456 ms\n",
"Wall time: 627 ms\n"
]
},
{
"data": {
"image/png": "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\nW/eWqSQfpmvK8sLqHhMmaX7W9/Pb4+iaCJxF1x76KbOPrmXG/bcIptrMY60FJTvQtR+6O3Bmu7tz\n5rMLq2rsG80kSZKk5WhRbkBM9ySJg+hqvy5jYW98kyRJkpbEJtNeQLrHjx1EdwPazF315yXZuqrO\na08U+O2YaU2yJUmStCiqat6PfZ16Mk33iKCTq+odA8MOoXuu7VvonuP6+RHTAbBYzVC0cuy7777s\nu+++Sx2GlhnLhUaxXGgUy4W23mFHtnzj2k+b/Pme240Ze3ZTTaaTPIjuweYnJTmerjnHq+iS6M8k\neTbdc02fNM04JEmSpGmYajJdVd8BNh7z8Z9Nc9mSJEnStPkGRK04q1atWuoQtAxZLjSK5UKjWC60\nkBbt0Xh9JKnlHJ8kSZJWnnFtpvvcgGjNtCRJktSTybQkSZLUk8m0JEmS1JPJtCRJktSTybQkSZLU\nk8m0JEmS1JPJtCRJktSTybQkSZLUk8m0JEmS1JPJtCRJktSTybQkSZLUk8m0JEmS1JPJtCRJktST\nybQkSZLUk8m0JEmS1JPJtCRJktSTybQkSZLUk8m0JEmS1JPJtCRJktSTybQkSZLUk8m0JEmS1JPJ\ntCRJktSTybQkSZLUk8m0JEmS1JPJtCRJktSTybQkSZLUk8m0JEmS1JPJtCRJktSTybQkSZLUk8m0\nJEmS1JPJtCRJktSTybQkSZLUk8m0JEmS1JPJtCRJktSTybQkSZLUk8m0JEmS1JPJtCRJktSTybQk\nSZLUk8m0JEmS1JPJtCRJktSTybQkSZLUk8m0JEmS1JPJtCRJktSTybQkSZLUk8m0JEmS1JPJtCRJ\nktSTybQkSZLUk8m0JEmS1JPJtCRJktSTybQkSZLUk8m0JEmS1JPJtCRJktSTybQkSZLUk8m0JEmS\n1JPJtCRJktSTybQkSZLUk8m0JEmS1JPJtCRJktSTybQkSZLUk8m0JEmS1JPJtCRJktSTybQkSZLU\nk8m0JEmS1JPJtCRJktSTybQkSZLUk8m0JEmS1JPJtCRJktSTybQkSZLUk8m0JEmS1JPJtCRJktST\nybQkSZLUk8m0JEmS1JPJtCRJktTTVJPpJB9Mcl6SEweG7ZPkrCTHtb9HTjMGSZIkaVqmXTO9P/CI\nEcPfVlW7tL8vTzkGSZIkaSqmmkxX1beBi0Z8lGkuV5IkSVoMS9Vm+nlJTkjygSRbLFEMkiRJ0jpZ\nimT63cDtq+pewG+Aty1BDJIkSdI622SxF1hV5w/0vh84dLbx991339Xdq1atYtWqVVOJS5IkSRuO\ny08+mstPOXqd55OqWoBwZllAsgNwaFXdo/Xfqqp+07pfDOxaVXuMmbamHZ8kSZI2LFvvsCNbvvHI\ntYb9fM/tqKp539c31ZrpJJ8AVgFbJTkD2AfYPcm9gGuBXwN7TzMGSZIkaVqmmkyPqXHef5rLlCRJ\nkhaLb0CUJEmSejKZliRJknoymZYkSZJ6MpmWJEmSejKZliRJknoymZYkSZJ6MpmWJEmSejKZliRJ\nknoymZYkSZJ6MpmWJEmSejKZliRJknoymZYkSZJ6MpmWJEmSejKZliRJknoymZYkSZJ6MpmWJEmS\nejKZliRJknoymZYkSZJ6MpmWJEmSejKZliRJknoymZYkSZJ62mSuEZJsBNwT2Aa4AvhxVf122oFJ\nkiRJy93YZDrJHYCXA38GnAqcD9wQ2CnJ5cB7gY9U1bWLEagkSZK03MxWM/164D3A3lVVgx8kuSWw\nB/B04CPTC0+SJElavsYm01X11Fk++y2w31QikiRJklaI2Zp5/PVsE1bV5xY+HEmSJGnlmK2Zx2Pb\n/1sCfwJ8vfXvDnwXMJmWJEnSBm22Zh7PAkhyOHDXqjq39d8a+PCiRCdJkiQtY5M8Z3q7mUS6OQ+4\n7ZTikSRJklaMOZ8zDXwtyVeAT7b+JwNHTC8kSZIkaWWYM5muqucl+SvgoW3Q+6rq4OmGJUmSJC1/\nk9RMAxwHXFpVRyTZNMlmVXXpNAOTJEmSlrs520wneQ5wEN0bDwG2Bf53mkFJkiRJK8EkNyA+F3gQ\ncAlAVZ1K97g8SZIkaYM2STJ9ZVVdNdOTZBOgZhlfkiRJ2iBMkkwfleRVwI2S/DlwIHDodMOSJEmS\nlr9JkulXAOcDJwF7A4dV1aunGpUkSZK0AkzyNI89gU9V1ftnBiR5TFV9YXphSZIkScvfJDXT7wS+\nleQuA8P+dUrxSJIkSSvGJMn0acCzgYOSPLENy/RCkiRJklaGSZp5VFUdl2Q34JNJ7g9sPOW4JEmS\npGVvkprpcwGq6gLgEXSPxbv7NIOSJEmSVoI5k+mqevRA97VV9bKqmiQJlyRJktZrY5t5JNmvql6U\n5FBGvKSlqv5yqpFJkiRJy9xsbaYPaP/fuhiBSJIkSSvN2GS6qn7Y/h+1eOFIkiRJK8dszTxOYkTz\n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\nbJpBSZIkSSvBJDXTfwX8JfAHgKo6B9hsmkFJkiRJK8EkyfRVVVVAASS58XRDkiRJklaGSZLpzyR5\nL7BlkucARwDvn25YkiRJ0vI3ydM83prkz4FLgDsB/1JVX516ZJIkSdIyN2synWRj4Iiq2h0wgZYk\nSZIGzNrMo6quAa5NssUixSNJkiStGJO8AfEy4KQkX6U90QOgql4wtagkSZKkFWCSZPpz7U+SJEnS\ngLHJdJLbVtUZVfWRxQxIkiRJWilmazP9vzMdST67CLFIkiRJK8psyXQGum8/7UAkSZKklWa2ZLrG\ndEuSJEli9hsQ75nkEroa6hu1blp/VdXmU49OkiRJWsbGJtNVtfFiBiJJkiStNLO+tEWSJEnSeCbT\nkiRJUk8m05IkSVJPJtOSJElSTybTkiRJUk8m05IkSVJPJtOSJElSTybTkiRJUk8m05IkSVJPJtOS\nJElSTybTkiRJUk8m05IkSVJPJtOSJElST5ssdQCSJEnSNN3nQbtx1tnnrO6/8KKL2HKB5m0yLUmS\npPXaWWefw5ZvPHJ1//l777xg87aZhyRJktSTybQkSZLUk8m0JEmS1NOStZlO8mvgYuBa4Oqqut9S\nxSJJkiT1sZQ3IF4LrKqqi5YwBkmSJKm3pWzmkSVeviRJkrROljKZLeCrSY5N8pwljEOSJEnqZSmb\neTyoqs5Ncgu6pPqUqvr2EsYjSZIkzcuSJdNVdW77f36Sg4H7AddJpvfdd9/V3atWrWLVqlWLFKEk\nSZLWV5effDSXn3L0Os9nSZLpJJsCG1XVZUluDDwceN2ocQeTaUmSJGkhbHrXB7LpXR+4uv/Cz729\n13yWqmZ6a+DgJNVi+HhVHb5EsUiSJEm9LEkyXVWnAfdaimVLkiRJC8VH00mSJEk9mUxLkiRJPZlM\nS5IkST2ZTEuSJEk9mUxLkiRJPZlMS5IkST2ZTEuSJEk9mUxLkiRJPZlMS5IkST2ZTEuSJEk9mUxL\nkiRJPZlMS5IkST2ZTEuSJEk9mUxLkiRJPZlMS5IkST1tstQBSJIkSQvlPg/ajbPOPmetYRdedBFb\nTml5JtOSJElab5x19jls+cYj1xp2/t47T215NvOQJEmSejKZliRJknoymZYkSZJ6MpmWJEmSejKZ\nliRJknoymZYkSZJ6MpmWJEmSejKZliRJknoymZYkSZJ6MpmWJEmSejKZliRJknoymZYkSZJ6MpmW\nJEmSejKZliRJknoymZYkSZJ6MpmWJEmSetpkqQOQJEmS+rrPg3bjrLPPWd1/4UUXseUiLt9kWpIk\nSSvWWWefw5ZvPHJ1//l777yoy7eZhyRJktSTybQkSZLUk8m0JEmS1NOybzP9l0/da3X3zne5E6//\nl1cvYTSSJEnSGsu+ZvqEnf6KE3b6K47b/uF84sDPLnU4kiRJ0mrLvmb6RnfaFYBrLr+Ea5c4FkmS\nJGnQsq+ZliRJkpYrk2lJkiSpp2XfzEOSJEmC677tEBb/jYfDVlQyffZZZ7H1DjuuNew2227DD79z\n1BJFJEmSpMUy/LZDWPw3Hg5bUcn0H6+55job8KxX7b5E0UiSJGlDt6KS6VEuvOjCtWqrR9VUD18S\nsDZbkiRJC2HFJ9PXXFtr1VaPqqkeviRgbbYkSZIWwopPpocN11R3w5a2YbokSZLWT+tdMj1cUw1L\n3zBdkiRJ66f1LpmexKjaa9tRS5Ikab42yGR6VO31if9wT29klCRJWiKjniF96WWXsdlNbrK6fzk2\n3d0gk+lRhhPs4eQauh14+/ecsLrfGxklSZIWxrhnSG/3X8eu1b/cmEyPYdtrSZKk6RmuiV6Otc6T\nMJmWJEnSohuuiV6plZYm0+vAGxklSZI2bCbT62CSGxmHG86DCbckSdL6wmR6gQ0n2MMN52HuJ4eM\nupvVBFySJGn5MZleAnM9OWT4qSHgk0MkSdLyNEkl4KhxVuoNh8NMppeBUbXZw4bbZy/mc7CtKZck\nSeOMeqTdcCXguMferQ9MpleI4YR7VE31cEEd9azs4Tbck7TpnuQgkSRJmjFcCbi+1EKPYjK9Qo16\nkshwQR33rOzhh58Pt+meJFGepKZckiRtmCa56r6+MJleoab5UplJfk1OUlPu69clSdL6zmRa17FQ\nvyaHm4fYNESSpOVt1H1SczURXZ+bcEzCZFoLYpJmJ330vUPYWnBJkuZv3I2CszURXZ+bcEzCZFoL\nYpJmJ8MJ90Ld/OgNkpIk9TNcIbWh1zL3YTKtRdPnhTajDupJ2nR7g6QkaUOyLs96Hny3xYZey9yH\nybSWlUnaa/cZZ0O5QdImL5K0YdrQn/W8lEymtUEY16Z78Nd436Yhyykpn+Rkajt0SVrehs/Bo5pF\nehPg8mEyrQ1C30cJTnJCG07K+7wsZ5L24wtlVMI9ySvth8fpE7NJ+vpvOf24lJajSY6R4fP0qGaR\nk9wEuCG9OGUpmUxLzSS11+NOaIP6vCxnkpfnTDMR7du8Zr4v/JkkkV/MHxajmAyuGx+JqVEW6rha\nyuNzkmX3SZSneYxsSC9OWUom01IzzRfh9DGqRmGu2uK+N2wulLme2DLJC4AmuTF1kkuek3zJTnIz\nzkI1/+kT30KZ5LmxC5XcLGXN13JrwjTJla3FjK9PPH3mO80EcqHm0ycxnuQq5KTjbLlW/3QeLavF\nYzItLVPTuhlzmj8Q5kqM+y57koR7eNgkzW1G/UCZ65GO0P8O+cH4JkkCFioJnuS5saO217SeBNAn\nkZnmozSH173PD7G+l+r7xNc3KZ/kSlufH659foCOOq4maf42SSI6yTEyvJ0nSYwnvQo5jXG0vJlM\nS1ovTdrcps98JmljPte8J0kCxs23z4+GuWq5FnM9J0m+JklEJ7kyM4nhde/zQ2yxL9VPsi3mu68m\nXdZcx9EkNa19msONWtYk85mkdtiEVuvCZFqS5mkhavunmexP84rAus5j1Hz6XuaeJL4+zZz6bNO+\n67BQzbCWU9vY5ZaYLrd4tP5ZsmQ6ySOB/YCNgA9W1VuWKhZJ0tKZZrKzWElm33VYTkmwpH42WoqF\nJtkI+G/gEcDdgKcmufNSxKKVp/549VKHoGXIcqFRLBcaxXKhhbQkyTRwP+DUqjq9qq4GPgU8boli\n0UpzzR+XOgItR5YLjWK50CiWCy2gpUqmtwXOHOg/qw2TJEmSVoxlfwPiVR9/NdBdkglZ4mgkSZKk\nNVJVi7/Q5AHAvlX1yNb/CqCGb0JMsvjBSZIkaYNUVfOuuV2qZHpj4GfAnwLnAscAT62qUxY9GEmS\nJKmnJWnmUVXXJHkecDhrHo1nIi1JkqQVZUlqpiVJkqT1wVI9zWMtSR6Z5KdJfp7k5WPG+a8kpyY5\nIcm9FjtGLa65ykSSPZL8qP19O8k9liJOLa5JzhVtvF2TXJ3krxczPi2NCb9DViU5PsmPkxw5ahyt\nXyb4Htk8ySEtrzgpyTOXIEwtsiQfTHJekhNnGWdeOeeSJ9OTvMAlyaOAO1TVjsDewP8seqBaNBO+\n1OdXwEOr6p7A64H3L26UWmyTvuypjfdm4CuLG6GWwoTfIVsA7wIeU1V3B5646IFqUU14vngu8JOq\nuhewO/CfSZb9U860zvanKxcj9ck5lzyZZrIXuDwO+ChAVX0f2CLJ1osbphbRnGWiqr5XVRe33u/h\n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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f9c46bd60d0>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%time\n",
"vals_css = sims_cats.collect() # maybe we need to subsample!\n",
"temp3 = []\n",
"for i in vals_css:\n",
" if i[1] > 0:\n",
" temp3.append(i[1]) #store it on the client machine (locally) as a list\n",
"n, bins, patches = plt.hist(temp3, 150, normed=1, facecolor=lb, alpha=0.85)\n",
"plt.xlabel('Pairwise Cosine similarity in non-addons features')\n",
"plt.ylabel('Frequency (normalized)')\n",
"plt.title('Distribution in pairwise similarity in non-addons sense for 5% sample of longitudinal (excluding 0 vals)')\n",
"plt.ylim(0,20)\n",
"plt.xlim(0,1)"
]
},
{
"cell_type": "code",
"execution_count": 163,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(0.12446746019568312, 0.21963964760735033)\n"
]
}
],
"source": [
"p = pearsonr(temp2[1:100], temp3[1:100]) # must be the same shape!!\n",
"print p"
]
},
{
"cell_type": "code",
"execution_count": 164,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[((u'95d67beb-7650-43a5-b653-5df67601c259',\n",
" u'a3117e49-e355-4a89-9b95-ab7719f2ca51'),\n",
" 0.0,\n",
" 0.81150791682082013)]"
]
},
"execution_count": 164,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sims_combined_rdd = sims_addon.join(sims_cats).map(lambda p: ((p[0]), p[1][0], p[1][1]))\n",
"sims_combined_rdd.take(1)"
]
},
{
"cell_type": "code",
"execution_count": 187,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"ADDON_SIM_THRESHOLD = 0.5\n",
"\n",
"ss_rdd = sims_combined_rdd.filter(lambda x: x[1] >= ADDON_SIM_THRESHOLD).map(lambda p: p[1])\n",
"ds_rdd = sims_combined_rdd.filter(lambda x: x[1] < ADDON_SIM_THRESHOLD).map(lambda p: p[1])\n",
"\n",
"LR_vals_x = np.arange(0,1,0.0001)"
]
},
{
"cell_type": "code",
"execution_count": 188,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.904042043145 0.154106011662\n",
"0.00372975595189 0.0274382167049\n"
]
}
],
"source": [
"def exponential_func(x, a, b, c):\n",
" return a * np.exp(-b * x) + c\n",
"# later this may be handy\n",
"\n",
"ss_mu = ss_rdd.mean()\n",
"ss_sig = ss_rdd.sampleStdev()\n",
"ds_mu = ds_rdd.mean()\n",
"ds_sig = ds_rdd.sampleStdev()\n",
"\n",
"print ss_mu, ss_sig\n",
"print ds_mu, ds_sig\n",
"# Find density estimates for the given values\n",
"#LR_vals_y_norm = scipy.stats.norm(ss_mu, ss_sig).pdf(LR_vals_x)/scipy.stats.norm(ds_mu, ds_sig).pdf(LR_vals_x) #LR right here!\n",
"\n",
"#poly_model_norm = np.polyfit(LR_vals_x, LR_vals_y_norm, 3)# fit the 3rd order polynomial, make sure this is ok by exmaining residuals later on!popt, pcov = curve_fit(func, x, y, p0=(1, 1e-6, 1))\n",
"#popt, pcov = scipy.optimize.curve_fit(exponential_func, LR_vals_x, LR_vals_y_norm, method='lm')\n",
"#exponential_model_norm = exponential_func(LR_vals_x, *popt)\n",
"#LR_vals_y_norm_prime = np.polyval(poly_model_norm, LR_vals_x)# sanity check!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Compute model densities for the two groups using KDE!"
]
},
{
"cell_type": "code",
"execution_count": 189,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"10000\n",
"1291\n"
]
}
],
"source": [
"from pyspark.mllib.stat import KernelDensity\n",
"\n",
"# Construct the density estimator with the sample data and a standard deviation for the Gaussian\n",
"# kernels\n",
"\n",
"BandWidth = 0.35\n",
"\n",
"kd_ss = KernelDensity()\n",
"kd_ss.setSample(ss_rdd)#.map(lambda p: p[1]))\n",
"kd_ss.setBandwidth(BandWidth)\n",
"\n",
"kd_ds = KernelDensity()\n",
"kd_ds.setSample(ds_rdd)#.map(lambda p: p[1]))\n",
"kd_ds.setBandwidth(BandWidth)\n",
"\n",
"num_kde_vals = kd_ss.estimate(LR_vals_x);\n",
"den_kde_vals = kd_ds.estimate(LR_vals_x);\n",
"\n",
"LR_vals_y_kde = num_kde_vals/den_kde_vals # LR right here!\n",
"\n",
"print len(LR_vals_y_kde)\n",
"print ss_rdd.count()"
]
},
{
"cell_type": "code",
"execution_count": 190,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x7f9c46c24d10>"
]
},
"execution_count": 190,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n7du39+0vItq9e3fdvXu35uTkaJ06dfS9995TVdXevXvr+PHjVVX10KFD+tlnn/n283g8unbtWlVV\nvfnmm3X06NEB+WrYsKF+9NFHqqo6ZcoUbdeunebl5WlBQYHefvvt2rt3b1VVnTp1ql511VV68OBB\nLS4u1v/85z+6Z8+eI46zoKBAMzIy9Mknn9TCwkKdN2+e1qhRw5fuRx99pElJSfrNN99oQUGBDh48\nWC+++GJVVd2xY4fGx8friy++qEVFRfrSSy9pfHy87tixQ1VV27Vrp3fffbcWFBTokiVLtHbt2r7r\nF2zZsmUaGxvrO7a8vDxdvXq1qqouWLBA169fr6qqS5Ys0ejoaP3vf/+rqqqLFi3S6tWr69ixY7Ww\nsFAXLFig0dHRumvXLlVVveGGG/SGG27QAwcO6IoVKzQ1NTWgvPmf75K2LW3Z9OrZs6cOHDhQDxw4\noNu2bdO2bdvqs88+G/L4hw8frhdffLHu2rVLN27cqGeddZamp6erqurhw4e1SZMm+vDDD+vhw4f1\n448/1tq1a+uaNWtU1SknSUlJ+vXXX2tRUZH+6U9/8pWDkq5Rx44dNSMjQ3/44QctKirSX375RWNi\nYvTHH39UVdUtW7boypUrQ+Y53LPKGGNM5fpf/iHlH+t+fTnP67LVV8u648n+OtqKfP7DHTSvH+X2\nyn+4Q8h0wvnpp5+0bt26+uGHH+rhw4cDwoIr2B6PRzdv3uwLT0xM1FdeecW33KtXL3388cdV9ciK\nfLD4+Hj99ttvw6azYcMG37YlVeRVVVu0aKEffvihqqo+9dRTesUVV4RMd9asWdquXbuAdWlpab74\nLr/8cp02bZovrKioSKOjozUnJ0dVnYr80qVLfeHXX3+9PvLII6qq2rdvX73tttt048aNR6QrIqWu\nyDdv3lw//vhjX1heXp5GRUVpUVGRTps2TS+44ALfuQtnyZIlmpaWFrDuwgsv9KU7YMAAHT58uC9s\n7969WqNGDc3OztYXXnhB27ZtG7Bvu3btdObMmZqTk6NRUVG6f/9+X1ifPn3CVuRvu+02veuuuyLm\n1atnz576xBNPqKpTkY+OjvZdc1XV5ORkXbZsmRYVFWlUVJSvwquqOmrUqIDy5j3fpdk2WLiyqaq6\ndetWPeWUU/TgwYO+dS+99JJ26tQpZFynn366vv/++77lZ5991leRX7JkidavXz9g+969e+u4ceNU\n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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f9c475c12d0>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.plot(LR_vals_x, num_kde_vals, color=do, linewidth=3.5)\n",
"plt.plot(LR_vals_x, den_kde_vals, color=db, linewidth=3.5)\n",
"plt.plot(LR_vals_x, LR_vals_y_kde, color=lb, linewidth=3.5)\n",
"\n",
"plt.xlabel('Observed pariwise non-addon similarity')\n",
"plt.ylabel('Likelihood Ratio of observing high addon-similarity \\n given observed non-addon similarity')\n",
"plt.title('Function relating two senses of similarity (common source score-based LR model)')\n",
"plt.legend(['simialrity densities good candidate donors', 'similarity densities poor candidate donors', 'likelihood ratio'], loc=2)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### define addon_donners subset\n",
"\n",
"### define the mapping to get a ranked list of ranked paired users\n",
"\n",
"### weight the addons by their donner's LR value\n",
"\n",
"### aggregate (sum) and deduplicate to addon-LRagg RDD then sort\n",
"\n",
"### recomend top n addons"
]
},
{
"cell_type": "code",
"execution_count": 206,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"NEW_USER_ID = \"068555da-f387-4549-ae09-968589b33865\"\n",
"# subset_addon_rdd.map(lambda p: (p['client_id'], p['active_addons'].keys())).map(lambda p: (p[0], filterSystemAddons(p[1], ADDON_EXCLUSION_LIST))).filter(lambda p: len(p[1])>1).take(100)\n",
"# find a candidate user that is interesting\n",
"# d508f84d-1abe-42af-b714-a92b1a0193f4\n",
"# ac04b744-0280-4368-a2a2-c4015badc3ac\n",
"# 068555da-f387-4549-ae09-968589b33865"
]
},
{
"cell_type": "code",
"execution_count": 207,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def calcKDE_LR(ss_model, ds_model, score):\n",
" return (ss_model.estimate(score)/ds_model.estimate(score))\n",
" # this can be faster if we pre-fir the KDE stuff with a polynomial or exponential model that is parametric and callable\n",
"\n",
"def generate_one_versus_rest_comparison(rdd_donnors, new_user_id, new_user_cats):\n",
" #newUSRnew_user = new_user.collect()\n",
" comp_rdd = rdd_donnors.map(lambda p: ((p[0],p[1]), (new_user_id, new_user_cats)) ) \n",
" return comp_rdd"
]
},
{
"cell_type": "code",
"execution_count": 208,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2454\n"
]
}
],
"source": [
"# generate the donor pool of add-ons\n",
"new_subset_cat_tokenized_rdd = freshPings_cat_DF.rdd.sample(False, 0.0005).map(lambda p: tokenize_catVar(p)).filter(lambda p: exclude_empty_entities(p))\n",
"print new_subset_cat_tokenized_rdd.count()"
]
},
{
"cell_type": "code",
"execution_count": 209,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[(u'068555da-f387-4549-ae09-968589b33865', ['loc_ru', 'sys_mem_2013', 'e10_bool_False', 'geo_country_RU', 'scrnWd_[1280]', u'default_search_ascii_text_fail_sauce', 'telemetry_bool_False', 'theme_{972ce4c6-7e08-4474-a285-3208198ce6fd}', 'virt_mem_None', 'os_Windows_NT', 'channel_release'])]\n",
"[(u'068555da-f387-4549-ae09-968589b33865', [u'fxdevtools-adapters@mozilla.org', u'yasearch@yandex.ru', u'sovetnik@metabar.ru', u'{ca42e45e-2389-4e62-a7d6-11db0a4a9054}', u'adbhelper@mozilla.org', u'vb@yandex.ru'])]\n"
]
}
],
"source": [
"arbitrary_new_user_addons = subset_addon_rdd.filter(lambda p: p['client_id'] == NEW_USER_ID).map(lambda p: (p[0], filterSystemAddons(p[1], ADDON_EXCLUSION_LIST))).filter(lambda p: len(p[1])>1).cache()\n",
"arbitrary_new_user_cat = subset_cat_rdd.filter(lambda p: p['client_id'] == NEW_USER_ID).map(lambda p: tokenize_catVar(p)).collect()\n",
"print arbitrary_new_user_cat\n",
"print arbitrary_new_user_addons.collect()"
]
},
{
"cell_type": "code",
"execution_count": 210,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"compRDD_newUser = generate_one_versus_rest_comparison(new_subset_cat_tokenized_rdd, arbitrary_new_user_cat[0][0], arbitrary_new_user_cat[0][1])"
]
},
{
"cell_type": "code",
"execution_count": 211,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[((u'bfa87fe1-7c67-f74c-a861-fc85746946ab', ['loc_en-US', 'sys_mem_4096', 'e10_bool_False', 'geo_country_CA', 'scrnWd_[1440]', 'default_search_Google', 'telemetry_bool_False', 'theme_{972ce4c6-7e08-4474-a285-3208198ce6fd}', 'virt_mem_None', 'os_Darwin', 'channel_release']), (u'068555da-f387-4549-ae09-968589b33865', ['loc_ru', 'sys_mem_2013', 'e10_bool_False', 'geo_country_RU', 'scrnWd_[1280]', u'default_search_ascii_text_fail_sauce', 'telemetry_bool_False', 'theme_{972ce4c6-7e08-4474-a285-3208198ce6fd}', 'virt_mem_None', 'os_Windows_NT', 'channel_release']))]\n"
]
}
],
"source": [
"print compRDD_newUser.take(1)"
]
},
{
"cell_type": "code",
"execution_count": 212,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"#newSIMS = \n",
"new_sims_to_donors = compRDD_newUser.map(lambda p: computeOtherSim(p)).cache()\n",
"#compRDD_newUser.take(1)"
]
},
{
"cell_type": "code",
"execution_count": 213,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.text.Text at 0x7f9c4e27e210>"
]
},
"execution_count": 213,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\nxAAAAABJRU5ErkJggg==\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f9c3e191690>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#numerator_vals = new_sims.map(lambda p: kd_ss.estimate(p[1]))\n",
"sim_dict_new_user = new_sims_to_donors.filter(lambda p: p[0][0] != NEW_USER_ID).map(lambda p: (p[0][0], p[1])).collectAsMap()\n",
"#print lrs_new_user.take(10)\n",
"\n",
"LR_vals_new_user = kd_ss.estimate(sim_dict_new_user.values())/kd_ds.estimate(sim_dict_new_user.values()) # LR right here!\n",
"plt.plot(LR_vals_new_user)\n",
"plt.xlabel('Arbitrary index into a candidate addon donor')\n",
"plt.ylabel('Likelihood Ratio of observing high addon-similarity \\n between new user and candidate donor')\n",
"plt.title('Examining similar users to find good addon donors')"
]
},
{
"cell_type": "code",
"execution_count": 214,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"LR_DICT = dict(zip(sim_dict_new_user.keys(),LR_vals_new_user))"
]
},
{
"cell_type": "code",
"execution_count": 215,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def assignLRval(p, Dictonary_of_lrs):\n",
" outlist = []\n",
" for i in p[1]:\n",
" outlist.append((i,log(Dictonary_of_lrs[p[0]])))\n",
" return outlist\n",
"\n",
"def assignOnes(p):\n",
" outlist = []\n",
" for i in p[1]:\n",
" outlist.append((i,1.0))\n",
" return outlist\n",
"\n",
"def getAddonNames(p, n):\n",
" st_a = \"http://addons.mozilla.org/api/v3/addons/addon/\";\n",
" st_c= \"/\"\n",
" #print p[0][0]\n",
" recomendations = []\n",
" for i in p: \n",
" st_b = str(i[0])\n",
" url = st_a + st_b + st_c\n",
"# print url\n",
" try:\n",
" r = urllib2.urlopen(url)\n",
" data = json.load(r) \n",
" recomendations.append(data['name'].values()[0])\n",
" print url\n",
"# recomendations.append(data)\n",
" #data = json.loads(r.read().decode(r.info().get_param('charset') or 'utf-8'))\n",
" except IOError:\n",
" True\n",
" #print \"addon information unreachable\"\n",
"# print recomendations\n",
" return recomendations[1:n]"
]
},
{
"cell_type": "code",
"execution_count": 216,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"donnor_ids = [x[0] for x in LR_DICT.items()]\n",
"donnor_lrs = [log(x[1]) for x in LR_DICT.items()]\n",
"\n",
"### two strategies for agregating the results here:\n",
"# 1. using summation (will include more bias for more frequently installed addons in the donor list independent of LR score)\n",
"# 2. using average (will emphgasize similarity very agressively, which may remove top n from recomendations)\n",
"### uncomment desired strategy:\n",
"\n",
"###### Strategy 1: Summation\n",
"final_ranking_of_addons = subset_addon_tok_filtered_rdd.filter(lambda p: p[0] in donnor_ids).flatMap(lambda p: assignLRval(p, LR_DICT))\\\n",
" .foldByKey(0,add)\n",
"\n",
"###### Strategy 2: Averaging\n",
"#final_ranking_of_addons = subset_addon_tok_filtered_rdd.filter(lambda p: p[0] in donnor_ids).flatMap(lambda p: assignLRval(p, LR_DICT))\\\n",
"# .aggregateByKey((0,0), lambda a,b: (a[0] + b, a[1] + 1),lambda a,b: (a[0] + b[0], a[1] + b[1])).mapValues(lambda v: v[0]/v[1]).cache()"
]
},
{
"cell_type": "code",
"execution_count": 217,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"068555da-f387-4549-ae09-968589b33865\n",
"['loc_ru', 'sys_mem_2013', 'e10_bool_False', 'geo_country_RU', 'scrnWd_[1280]', u'default_search_ascii_text_fail_sauce', 'telemetry_bool_False', 'theme_{972ce4c6-7e08-4474-a285-3208198ce6fd}', 'virt_mem_None', 'os_Windows_NT', 'channel_release']\n"
]
}
],
"source": [
"print arbitrary_new_user_cat[0][0]\n",
"print arbitrary_new_user_cat[0][1]"
]
},
{
"cell_type": "code",
"execution_count": 218,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"http://addons.mozilla.org/api/v3/addons/addon/{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}/\n",
"http://addons.mozilla.org/api/v3/addons/addon/{82AF8DCA-6DE9-405D-BD5E-43525BDAD38A}/\n",
"http://addons.mozilla.org/api/v3/addons/addon/easyscreenshot@mozillaonline.com/\n",
"http://addons.mozilla.org/api/v3/addons/addon/vb@yandex.ru/\n",
"http://addons.mozilla.org/api/v3/addons/addon/{b9db16a4-6edc-47ec-a1f4-b86292ed211d}/\n",
"http://addons.mozilla.org/api/v3/addons/addon/yasearch@yandex.ru/\n",
"http://addons.mozilla.org/api/v3/addons/addon/{DDC359D1-844A-42a7-9AA1-88A850A938A8}/\n",
"http://addons.mozilla.org/api/v3/addons/addon/abb@amazon.com/\n",
"http://addons.mozilla.org/api/v3/addons/addon/elemhidehelper@adblockplus.org/\n",
"http://addons.mozilla.org/api/v3/addons/addon/WebProtection@360safe.com/\n",
"http://addons.mozilla.org/api/v3/addons/addon/firebug@software.joehewitt.com/\n",
"http://addons.mozilla.org/api/v3/addons/addon/e67f8350-7edf-11e3-baa7-0800200c9a66@fri-gate.org/\n",
"http://addons.mozilla.org/api/v3/addons/addon/{bee6eb20-01e0-ebd1-da83-080329fb9a3a}/\n",
"http://addons.mozilla.org/api/v3/addons/addon/YoutubeDownloader@PeterOlayev.com/\n",
"http://addons.mozilla.org/api/v3/addons/addon/{e4a8a97b-f2ed-450b-b12d-ee082ba24781}/\n",
"http://addons.mozilla.org/api/v3/addons/addon/FirePHPExtension-Build@firephp.org/\n",
"http://addons.mozilla.org/api/v3/addons/addon/s3google@translator/\n",
"http://addons.mozilla.org/api/v3/addons/addon/{aff87fa2-a58e-4edd-b852-0a20203c1e17}/\n",
"http://addons.mozilla.org/api/v3/addons/addon/wappalyzer@crunchlabz.com/\n",
"http://addons.mozilla.org/api/v3/addons/addon/belgiumeid@eid.belgium.be/\n"
]
},
{
"data": {
"text/plain": [
"[u'Skype',\n",
" u'\\u7f51\\u9875\\u622a\\u56fe',\n",
" u'\\u0412\\u0438\\u0437\\u0443\\u0430\\u043b\\u044c\\u043d\\u044b\\u0435 \\u0437\\u0430\\u043a\\u043b\\u0430\\u0434\\u043a\\u0438 \\u043e\\u0442 \\u042f\\u043d\\u0434\\u0435\\u043a\\u0441',\n",
" u'Video DownloadHelper',\n",
" u'Yandex.Bar (\\u042f\\u043d\\u0434\\u0435\\u043a\\u0441 \\u0411\\u0430\\u0440)',\n",
" u'DownThemAll!',\n",
" u'Assistant Amazon',\n",
" u'Element Hiding Helper \\u0434\\u043b\\u044f Adblock Plus',\n",
" u'360 Internet Protection for Firefox']"
]
},
"execution_count": 218,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"addon_recommendations = final_ranking_of_addons.takeOrdered(40, key=lambda x: -x[1])\n",
"getAddonNames(addon_recommendations, 10)"
]
},
{
"cell_type": "code",
"execution_count": 219,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"http://addons.mozilla.org/api/v3/addons/addon/yasearch@yandex.ru/\n",
"http://addons.mozilla.org/api/v3/addons/addon/sovetnik@metabar.ru/\n",
"http://addons.mozilla.org/api/v3/addons/addon/vb@yandex.ru/\n"
]
},
{
"data": {
"text/plain": [
"[u'\\u0421\\u043e\\u0432\\u0435\\u0442\\u043d\\u0438\\u043a \\u042f\\u043d\\u0434\\u0435\\u043a\\u0441.\\u041c\\u0430\\u0440\\u043a\\u0435\\u0442\\u0430',\n",
" u'\\u0412\\u0438\\u0437\\u0443\\u0430\\u043b\\u044c\\u043d\\u044b\\u0435 \\u0437\\u0430\\u043a\\u043b\\u0430\\u0434\\u043a\\u0438 \\u043e\\u0442 \\u042f\\u043d\\u0434\\u0435\\u043a\\u0441']"
]
},
"execution_count": 219,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# display true addons installed\n",
"ground_truth = arbitrary_new_user_addons.map(lambda p: assignOnes(p)).collect()\n",
"getAddonNames(ground_truth[0], 10)"
]
},
{
"cell_type": "code",
"execution_count": 220,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[(u'068555da-f387-4549-ae09-968589b33865', [u'fxdevtools-adapters@mozilla.org', u'yasearch@yandex.ru', u'sovetnik@metabar.ru', u'{ca42e45e-2389-4e62-a7d6-11db0a4a9054}', u'adbhelper@mozilla.org', u'vb@yandex.ru'])]\n"
]
}
],
"source": [
"print arbitrary_new_user_addons.collect()"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"## Next steps?\n",
"### exploration of variable relationships?\n",
"### refine addon recomendations for users with existing addons"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.11"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
# coding: utf-8
# In[1]:
import numpy as np
import math
from pyspark.sql import SQLContext, Row
from moztelemetry import get_pings, get_pings_properties, get_one_ping_per_client, get_clients_history, get_records
import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import scipy.stats
import scipy.optimize
from scipy.stats.stats import pearsonr
import scipy.spatial.distance as spdist
import urllib2, json
get_ipython().magic(u'pylab inline')
matplotlib.rcParams['figure.figsize'] = (12.0, 6.0)
# In[2]:
RAND_SEED = 422950748
ADDON_EXCLUSION_LIST = ['loop@mozilla.org', 'firefox@getpocket.com', 'e10srollout@mozilla.org', 'firefox-hotfix@mozilla.org']
#mozColours
db = [0.00, 0.13, 0.28]
lb = [0.00, 0.59, 0.87]
lo = [1.00, 0.58, 0.00]
do = [0.90, 0.38, 0.00]
# In[66]:
get_ipython().run_cell_magic(u'time', u'', u'freshPings_addon_DF = sqlContext.sql("SELECT * FROM longitudinal")\\\n .where("active_addons IS NOT null and size(active_addons[0]) > 0")\\\n .where("size(active_addons) > 1")\\\n .where("size(active_addons) < 999")\\\n .where("build IS NOT null AND build[0].application_name = \'Firefox\'")\\\n .selectExpr("client_id as client_id", "active_addons[0] as active_addons")\n\n# .where("size(active_addons) > 1")\\\n# this is a temporayr hack to get aroudn the telemetry bug!!!! and should be removed when the issue is resolved.\n\nfreshPings_cat_DF = sqlContext.sql("SELECT * FROM longitudinal")\\\n .where("active_addons IS NOT null and size(active_addons[0]) > 0")\\\n .where("size(active_addons) > 1")\\\n .where("build IS NOT null AND build[0].application_name = \'Firefox\'")\\\n .selectExpr("client_id as client_id", "geo_country[0] as geo_country",\\\n "os as os",\\\n "system[0].memory_mb as sys_mem",\\\n "system[0].virtual_max_mb as virt_mem",\\\n "theme[0].id as theme",\\\n #"flash_version[0] as flash",\\\n "system_gfx[0].monitors.screen_width as scrnWd",\\\n #"number_of_profiles as prof_num",\\\n "settings[0].e10s_enabled as e10_bool",\\\n "settings[0].telemetry_enabled as telemetry_bool",\\\n "settings[0].default_search_engine_data.name as default_search",\\\n "settings[0].locale as loc",\\\n "settings[0].update.channel as channel"\\\n )\n\n# Thanks to Alessio, for being a BOSS\n\n"""\nfreshPings_con_DF = sqlContext.sql("SELECT * FROM longitudinal")\\\n .where("active_addons IS NOT null")\\\n .where("build IS NOT null AND build[0].application_name = \'Firefox\'")\\\n .selectExpr("client_id as client_id", "session_length[0] as session_length",\\\n "paint_build_displaylist_time[0] as paint_time", "predictor_wait_time[0] as predictor_wait_time",\\\n "html_background_reflow_ms_2[0] as reflow_ms", "telemetry_memory_reporter_ms[0] as tele_rep_time",\\\n "image_decode_latency_us[0] as im_decode_latency", "http_subitem_open_latency_time[0] as op_latent"\\\n )\n"""\n\nsubset_addon_rdd = freshPings_addon_DF.sample(False, 0.1, RAND_SEED).rdd.cache()\nsubset_addon_tok_rdd = subset_addon_rdd.map(lambda p: (p[\'client_id\'], p[\'active_addons\'].keys())).cache()\n\n# to filter by client_id\ndef isinSet(p):\n return p in valid_ID_in_addon_Set # this must be broadcast\n\ndef filterSystemAddons(p, ADDON_EXCLUSION_LIST):\n return [x for x in p if x not in ADDON_EXCLUSION_LIST]\n \nsubset_addon_tok_filtered_rdd = subset_addon_tok_rdd.map(lambda p: (p[0], filterSystemAddons(p[1], ADDON_EXCLUSION_LIST))).filter(lambda p: len(p[1])>1).cache()\n\nvalid_ID_in_addon_Set = set(subset_addon_tok_filtered_rdd.map(lambda p: p[0]).collect())#set of valid target ids that were randomly chosen for addons\nsc.broadcast(valid_ID_in_addon_Set)\n\nsubset_cat_rdd = freshPings_cat_DF.rdd.filter(lambda p: isinSet(p[0])).cache()')
# In[67]:
freshPings_cat_DF.take(1)
# In[68]:
print subset_cat_rdd.count()
print subset_addon_tok_filtered_rdd.count()
#subset_addon_tok_filtered_rdd.take(100)
# In[186]:
get_ipython().run_cell_magic(u'time', u'', u"# implement some standard nlp functions to work with addons\n\ndef addon_frequency(add_on_list):\n # we can cheat a bit here becasue we know the tf (token frequency is always 1/number_of_elements)\n addict = dict()\n l = len(add_on_list)\n for i in add_on_list:\n addict[i] = float(1)/l # quack quack!\n return addict # the dictionary of addon names (keys) to frequency (value)\n\ndef population_frequency(corpusRDD):\n total_pings = corpusRDD.count()\n addons_intf = corpusRDD.flatMap(lambda p: list(set(p[1]))) # in principal the <list(set())> is unnecessary but lets be safe!\n addonCountPairRDD = addons_intf.map(lambda p: (p,1)) # creating a pairRDD with integer 1's all over the values\n addonSumPairRDD = addonCountPairRDD.reduceByKey(add)\n population_frequency_addons = addonSumPairRDD.map(lambda p: (p[0], float(total_pings)/p[1])) #dividing the lexicon count by the frequency\n return population_frequency_addons\n\ndef addonRarity(addons_freq): \n # corpusIDFsBroadcast MUST be a broadcast variable or everything breaks down!\n # it must be a dict of {addon_name, frequency})\n addon_dict_intf = dict()\n \n t = float(1)/len(addons_freq)#if the possibility of duplicates exists then: <float(1)> becomes <float(addons_frequency.count(i))/len(addons_frequency) and goes inside the loop\n for i in addons_freq:\n addon_dict_intf[i] = t*corpus_addons_IDFs_Broadcast.get(i,1)\n return addon_dict_intf\n\ndef catVarRarity(cat_freq): \n # corpusIDFsBroadcast MUST be a broadcast variable or everything breaks down!\n # it must be a dict of {addon_name, frequency})\n dict_intf = dict()\n \n t = float(1)/len(addons_freq)#if the possibility of duplicates exists then: <float(1)> becomes <float(addons_frequency.count(i))/len(addons_frequency) and goes inside the loop\n for i in cat_freq:\n dict_intf[i] = t*corpusCatIDFsBroadcast.get(i,1)\n return addon_dict_intf\n\ndef convertKeyCombinedIDs(p):# need to combine the keys ping_ids into a concatenated string for the comparison \n # this will allow quick exploration of the \n source_1_id = str(p[0][0])\n source_2_id = str(p[0][1])\n similarity_score = p[1]\n return (source_1_id + ' ' + source_2_id, similarity_score)\n \ndef count_entities(p):\n tally_counter = p.map(lambda q: len(q[1])).reduce(add)\n return tally_counter\n\ndef exclude_empty_entities(p):\n return bool(p[1])#how pythonic \n\ndef addonID2addonName(a):\n return addonIdsToNames_broadcast[a]\n\ndef tokenize_catVar(p):\n names = p.asDict()\n del names['client_id']\n cat_list = []\n for i in names:\n staging_string = safe_unicode(i) + '_' + safe_unicode(names[i])\n cat_list.append(staging_string)\n return (p[0], cat_list)\n\ndef dotprod(x1,x2):\n idx = list(x1.viewkeys() & x2.viewkeys())\n dotProd = 0\n for i in idx:\n dotProd += x1.get(i,1)*x2.get(i,1)\n return dotProd\n\ndef norm(x):\n normVal = 0\n idx = list(x.viewkeys())\n for i in idx:\n normVal += (x.get(i,1)*x.get(i,1))\n return math.sqrt(normVal)\n\ndef cosSim(x1,x2):\n return dotprod(x1,x2)/norm(x1)/norm(x2)\n\ndef cosSimHelper(list_1,list_2):\n w1 = addonRarity(addon_frequency(list_1))\n w2 = addonRarity(addon_frequency(list_2))\n return cosSim(w1,w2) \n\ndef computeCosSim(pair_record):\n #requires the corpusIDFs to be broadcast!\n source_1 = pair_record[0]\n source_2 = pair_record[1]\n ping_id_1 = source_1[0]\n ping_id_2 = source_2[0]\n value_1 = source_1[1]\n value_2 = source_2[1]\n cs = cosSimHelper(value_1,value_2)\n return ((ping_id_1, ping_id_2),cs)\n\ndef computeOtherSim(pair_record):\n #requires the corpusIDFs to be broadcast!\n source_1 = pair_record[0]\n source_2 = pair_record[1]\n ping_id_1 = source_1[0]\n ping_id_2 = source_2[0]\n value_1 = source_1[1]\n value_2 = source_2[1]\n cs = otherSimHelper(value_1,value_2)\n return ((ping_id_1, ping_id_2),cs)\n\ndef otherSimHelper(list_1,list_2):\n w1 = catVarRarity(addon_frequency(list_1))\n w2 = catVarRarity(addon_frequency(list_2))\n return spdist.correlation(w1.values(), w2.values()) \n\ndef generate_nonCartesian_pairWiseComparison_RDD(rddq):\n rdd1,rdd2 = rddq.randomSplit([0.5,0.5], RAND_SEED)\n rdd1b = rdd1.zipWithIndex().map(lambda p: (p[1],p[0]))\n rdd2b = rdd2.zipWithIndex().map(lambda p: (p[1],p[0]))\n rddc = rdd1b.join(rdd2b).map(lambda p: p[1])\n return rddc\n\ndef safe_unicode(obj, *args):\n try:\n return str(obj, *args)\n except UnicodeEncodeError: \n return unicode('ascii_text_fail_sauce')\n\ndef catVarRarity(addons_freq): \n # corpusIDFsBroadcast MUST be a broadcast variable or everything breaks down!\n # it must be a dict of {addon_name, frequency})\n addon_dict_intf = dict()\n \n t = float(1)/len(addons_freq)#if the possibility of duplicates exists then: <float(1)> becomes <float(addons_frequency.count(i))/len(addons_frequency) and goes inside the loop\n for i in addons_freq:\n addon_dict_intf[i] = t*corpusCatIDFsBroadcast.get(i,1)\n return addon_dict_intf")
# In[150]:
get_ipython().run_cell_magic(u'time', u'', u"\nrecCNT = subset_addon_tok_filtered_rdd.count()\naddonCNT = count_entities(subset_addon_tok_filtered_rdd)\n\nprint str(recCNT) + ' records parsed including ' + str(addonCNT) +' addon installations' ")
# ### We will borrow many concepts from NLP here. but we have it easy, becasue our lexicon is only the total number of possible add-ons, so calculating IDF (inverse document frequency) and TF (token frequency) we can convert our add-ons list to a numerical vector representing each addon list as a vector of numerical weights favouring rare add-ons (in pairwise comparisons between users).
# ### This will take a long time! we use the superset that our small sample was drawn from to ensure that the set esclusion is empty. Then calculate the frequency of addons globally within the freshest part of the longitudinal corpus, once again excluding pings wiht no add-ons for now.
# In[151]:
get_ipython().run_cell_magic(u'time', u'', u"corpusTokenizedRDD = freshPings_addon_DF.map(lambda p: (p['client_id'], p['active_addons'].keys()))\ncorpusIDFs = population_frequency(corpusTokenizedRDD)\n## DISCUSSION POINT: should we include the subsample in the corpus:\n# option 1: no, but then filter out addons we have not seen yet in the corpus, from the sample\n# option 2: yes leave the corpus as the super set and risk overfitting\ncorpus_addons_IDFs_Broadcast = corpusIDFs.collectAsMap()\nsc.broadcast(corpus_addons_IDFs_Broadcast) # this is really important, otherwise we are sending this to each worker FOR EACH partition!!!\n\ntokenized_catVars_corpus = subset_cat_rdd.map(lambda p: tokenize_catVar(p)).filter(lambda p: exclude_empty_entities(p)).cache()\n#cnt = tokenized_catVars_corpus.count()\ncorpusCatIDFs = population_frequency(tokenized_catVars_corpus) # idfs of the keys in the pair rdd\ncorpusCatIDFsBroadcast = corpusCatIDFs.collectAsMap() \nsc.broadcast(corpusCatIDFsBroadcast)#broadcast the idfs (this should be small)")
# In[152]:
get_ipython().run_cell_magic(u'time', u'', u"vals_idf = corpusIDFs.collect() # maybe we need to subsample!\ntemp = []\nfor i in vals_idf:\n temp.append(i[1]) #store it on the client machine (locally) as a list\n# plot with plotly \nn, bins, patches = plt.hist(temp, 150, normed=1, facecolor=db, alpha=0.85)\nplt.xlabel('document TF-IDF values observed \\n <- occurs in most users (less informative) | occurs rarely relative to corpus (more informative) ->')\nplt.ylabel('Frequency (normalized)')\nplt.title('token frequency for the entire addons corpus')\nplt.ylim(0, 0.000005)\nplt.xlim(0,5e6)")
# In[153]:
get_ipython().run_cell_magic(u'time', u'', u"# here is a nice place to exmaine the most and least frequent addons\nmostFrequent_addons = corpusIDFs.takeOrdered(20, lambda p: p[1])\nprint 'Most frequently installed add-ons (system addons not filtered): ' + str(mostFrequent_addons) + '\\n'\n\nleastFrequent_addons = corpusIDFs.takeOrdered(20, lambda p: -1*p[1])\nprint 'Least popular installed add-ons: ' + str(leastFrequent_addons)")
# ### Low popularity (rare) addons may still be very useful in recomending addons for some users. I.e. if two users have a similar profile in terms of rare characteristics, that is weighted more heavily than if they are similar in terms of very common characteristics.
# ### OK, now we need to compare pairwise similarity between addon weight vector
#
# In[154]:
get_ipython().run_cell_magic(u'time', u'', u'crossSmall_addons = generate_nonCartesian_pairWiseComparison_RDD(subset_addon_tok_filtered_rdd)\nprint crossSmall_addons.count()')
# In[155]:
get_ipython().run_cell_magic(u'time', u'', u'sims_addon = crossSmall_addons.map(lambda p: computeCosSim(p)).cache()\nprint sims_addon.take(10)')
# In[156]:
vals_css = sims_addon.collect() # maybe we need to subsample!
temp2 = []
for i in vals_css:
if i[1] > 0:
temp2.append(i[1]) #store it on the client machine (locally) as a list
n, bins, patches = plt.hist(temp2, 150, normed=1, facecolor=do, alpha=0.85)
plt.xlabel('Pairwise cosine similarity in addons features')
plt.ylabel('Frequency (normalized)')
plt.title('Distribution in pairwise similarity in addons sense for 5% sample of longitudinal (excluding 0 vals)')
plt.ylim(0, 20)
plt.xlim(0,1)
# ### it may be interesting to normalize these values by the number of add-ons in the comparison!
# # OK, lets try to relate the pairwise addon similarities to something else
# In[157]:
#freshPings_cat_DF.take(3)
subset_cat_rdd.take(1)
# ### Because these are categorical variables with a (small) finite set of possible values, we can use them almost exactly the same way as we did with addon names. This we we can reuse a lot of the code.
# In[158]:
tokenized_catVars = subset_cat_rdd.map(lambda p: tokenize_catVar(p))
print tokenized_catVars.take(1)
# ### then perform pairwise similarity comparisons and keep track of SS and SD compariosns in a list of id pairs
# In[159]:
crossSmall_cats = generate_nonCartesian_pairWiseComparison_RDD(tokenized_catVars)
sims_cats = crossSmall_cats.map(lambda p: computeOtherSim(p)).cache()
print sims_addon.take(1)
print sims_cats.take(1)
#crossSmall_cats.take(1)
# In[160]:
c = sims_addon.map(lambda p: p[0]).intersection(sims_cats.map(lambda p: p[0])).count()
# In[161]:
print c
# In[162]:
get_ipython().run_cell_magic(u'time', u'', u"vals_css = sims_cats.collect() # maybe we need to subsample!\ntemp3 = []\nfor i in vals_css:\n if i[1] > 0:\n temp3.append(i[1]) #store it on the client machine (locally) as a list\nn, bins, patches = plt.hist(temp3, 150, normed=1, facecolor=lb, alpha=0.85)\nplt.xlabel('Pairwise Cosine similarity in non-addons features')\nplt.ylabel('Frequency (normalized)')\nplt.title('Distribution in pairwise similarity in non-addons sense for 5% sample of longitudinal (excluding 0 vals)')\nplt.ylim(0,20)\nplt.xlim(0,1)")
# In[163]:
p = pearsonr(temp2[1:100], temp3[1:100]) # must be the same shape!!
print p
# In[164]:
sims_combined_rdd = sims_addon.join(sims_cats).map(lambda p: ((p[0]), p[1][0], p[1][1]))
sims_combined_rdd.take(1)
# In[187]:
ADDON_SIM_THRESHOLD = 0.5
ss_rdd = sims_combined_rdd.filter(lambda x: x[1] >= ADDON_SIM_THRESHOLD).map(lambda p: p[1])
ds_rdd = sims_combined_rdd.filter(lambda x: x[1] < ADDON_SIM_THRESHOLD).map(lambda p: p[1])
LR_vals_x = np.arange(0,1,0.0001)
# In[188]:
def exponential_func(x, a, b, c):
return a * np.exp(-b * x) + c
# later this may be handy
ss_mu = ss_rdd.mean()
ss_sig = ss_rdd.sampleStdev()
ds_mu = ds_rdd.mean()
ds_sig = ds_rdd.sampleStdev()
print ss_mu, ss_sig
print ds_mu, ds_sig
# Find density estimates for the given values
#LR_vals_y_norm = scipy.stats.norm(ss_mu, ss_sig).pdf(LR_vals_x)/scipy.stats.norm(ds_mu, ds_sig).pdf(LR_vals_x) #LR right here!
#poly_model_norm = np.polyfit(LR_vals_x, LR_vals_y_norm, 3)# fit the 3rd order polynomial, make sure this is ok by exmaining residuals later on!popt, pcov = curve_fit(func, x, y, p0=(1, 1e-6, 1))
#popt, pcov = scipy.optimize.curve_fit(exponential_func, LR_vals_x, LR_vals_y_norm, method='lm')
#exponential_model_norm = exponential_func(LR_vals_x, *popt)
#LR_vals_y_norm_prime = np.polyval(poly_model_norm, LR_vals_x)# sanity check!
# ### Compute model densities for the two groups using KDE!
# In[189]:
from pyspark.mllib.stat import KernelDensity
# Construct the density estimator with the sample data and a standard deviation for the Gaussian
# kernels
BandWidth = 0.35
kd_ss = KernelDensity()
kd_ss.setSample(ss_rdd)#.map(lambda p: p[1]))
kd_ss.setBandwidth(BandWidth)
kd_ds = KernelDensity()
kd_ds.setSample(ds_rdd)#.map(lambda p: p[1]))
kd_ds.setBandwidth(BandWidth)
num_kde_vals = kd_ss.estimate(LR_vals_x);
den_kde_vals = kd_ds.estimate(LR_vals_x);
LR_vals_y_kde = num_kde_vals/den_kde_vals # LR right here!
print len(LR_vals_y_kde)
print ss_rdd.count()
# In[190]:
plt.plot(LR_vals_x, num_kde_vals, color=do, linewidth=3.5)
plt.plot(LR_vals_x, den_kde_vals, color=db, linewidth=3.5)
plt.plot(LR_vals_x, LR_vals_y_kde, color=lb, linewidth=3.5)
plt.xlabel('Observed pariwise non-addon similarity')
plt.ylabel('Likelihood Ratio of observing high addon-similarity \n given observed non-addon similarity')
plt.title('Function relating two senses of similarity (common source score-based LR model)')
plt.legend(['simialrity densities good candidate donors', 'similarity densities poor candidate donors', 'likelihood ratio'], loc=2)
# ### define addon_donners subset
#
# ### define the mapping to get a ranked list of ranked paired users
#
# ### weight the addons by their donner's LR value
#
# ### aggregate (sum) and deduplicate to addon-LRagg RDD then sort
#
# ### recomend top n addons
# In[206]:
NEW_USER_ID = "068555da-f387-4549-ae09-968589b33865"
# subset_addon_rdd.map(lambda p: (p['client_id'], p['active_addons'].keys())).map(lambda p: (p[0], filterSystemAddons(p[1], ADDON_EXCLUSION_LIST))).filter(lambda p: len(p[1])>1).take(100)
# find a candidate user that is interesting
# d508f84d-1abe-42af-b714-a92b1a0193f4
# ac04b744-0280-4368-a2a2-c4015badc3ac
# 068555da-f387-4549-ae09-968589b33865
# In[207]:
def calcKDE_LR(ss_model, ds_model, score):
return (ss_model.estimate(score)/ds_model.estimate(score))
# this can be faster if we pre-fir the KDE stuff with a polynomial or exponential model that is parametric and callable
def generate_one_versus_rest_comparison(rdd_donnors, new_user_id, new_user_cats):
#newUSRnew_user = new_user.collect()
comp_rdd = rdd_donnors.map(lambda p: ((p[0],p[1]), (new_user_id, new_user_cats)) )
return comp_rdd
# In[208]:
# generate the donor pool of add-ons
new_subset_cat_tokenized_rdd = freshPings_cat_DF.rdd.sample(False, 0.0005).map(lambda p: tokenize_catVar(p)).filter(lambda p: exclude_empty_entities(p))
print new_subset_cat_tokenized_rdd.count()
# In[209]:
arbitrary_new_user_addons = subset_addon_rdd.filter(lambda p: p['client_id'] == NEW_USER_ID).map(lambda p: (p[0], filterSystemAddons(p[1], ADDON_EXCLUSION_LIST))).filter(lambda p: len(p[1])>1).cache()
arbitrary_new_user_cat = subset_cat_rdd.filter(lambda p: p['client_id'] == NEW_USER_ID).map(lambda p: tokenize_catVar(p)).collect()
print arbitrary_new_user_cat
print arbitrary_new_user_addons.collect()
# In[210]:
compRDD_newUser = generate_one_versus_rest_comparison(new_subset_cat_tokenized_rdd, arbitrary_new_user_cat[0][0], arbitrary_new_user_cat[0][1])
# In[211]:
print compRDD_newUser.take(1)
# In[212]:
#newSIMS =
new_sims_to_donors = compRDD_newUser.map(lambda p: computeOtherSim(p)).cache()
#compRDD_newUser.take(1)
# In[213]:
#numerator_vals = new_sims.map(lambda p: kd_ss.estimate(p[1]))
sim_dict_new_user = new_sims_to_donors.filter(lambda p: p[0][0] != NEW_USER_ID).map(lambda p: (p[0][0], p[1])).collectAsMap()
#print lrs_new_user.take(10)
LR_vals_new_user = kd_ss.estimate(sim_dict_new_user.values())/kd_ds.estimate(sim_dict_new_user.values()) # LR right here!
plt.plot(LR_vals_new_user)
plt.xlabel('Arbitrary index into a candidate addon donor')
plt.ylabel('Likelihood Ratio of observing high addon-similarity \n between new user and candidate donor')
plt.title('Examining similar users to find good addon donors')
# In[214]:
LR_DICT = dict(zip(sim_dict_new_user.keys(),LR_vals_new_user))
# In[215]:
def assignLRval(p, Dictonary_of_lrs):
outlist = []
for i in p[1]:
outlist.append((i,log(Dictonary_of_lrs[p[0]])))
return outlist
def assignOnes(p):
outlist = []
for i in p[1]:
outlist.append((i,1.0))
return outlist
def getAddonNames(p, n):
st_a = "http://addons.mozilla.org/api/v3/addons/addon/";
st_c= "/"
#print p[0][0]
recomendations = []
for i in p:
st_b = str(i[0])
url = st_a + st_b + st_c
# print url
try:
r = urllib2.urlopen(url)
data = json.load(r)
recomendations.append(data['name'].values()[0])
print url
# recomendations.append(data)
#data = json.loads(r.read().decode(r.info().get_param('charset') or 'utf-8'))
except IOError:
True
#print "addon information unreachable"
# print recomendations
return recomendations[1:n]
# In[216]:
donnor_ids = [x[0] for x in LR_DICT.items()]
donnor_lrs = [log(x[1]) for x in LR_DICT.items()]
### two strategies for agregating the results here:
# 1. using summation (will include more bias for more frequently installed addons in the donor list independent of LR score)
# 2. using average (will emphgasize similarity very agressively, which may remove top n from recomendations)
### uncomment desired strategy:
###### Strategy 1: Summation
final_ranking_of_addons = subset_addon_tok_filtered_rdd.filter(lambda p: p[0] in donnor_ids).flatMap(lambda p: assignLRval(p, LR_DICT)) .foldByKey(0,add)
###### Strategy 2: Averaging
#final_ranking_of_addons = subset_addon_tok_filtered_rdd.filter(lambda p: p[0] in donnor_ids).flatMap(lambda p: assignLRval(p, LR_DICT))\
# .aggregateByKey((0,0), lambda a,b: (a[0] + b, a[1] + 1),lambda a,b: (a[0] + b[0], a[1] + b[1])).mapValues(lambda v: v[0]/v[1]).cache()
# In[217]:
print arbitrary_new_user_cat[0][0]
print arbitrary_new_user_cat[0][1]
# In[218]:
addon_recommendations = final_ranking_of_addons.takeOrdered(40, key=lambda x: -x[1])
getAddonNames(addon_recommendations, 10)
# In[219]:
# display true addons installed
ground_truth = arbitrary_new_user_addons.map(lambda p: assignOnes(p)).collect()
getAddonNames(ground_truth[0], 10)
# In[220]:
print arbitrary_new_user_addons.collect()
# ## Next steps?
# ### exploration of variable relationships?
# ### refine addon recomendations for users with existing addons
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment