Showing preview only (2,964K chars total). Download the full file or copy to clipboard to get everything.
Repository: PacktPublishing/Learning-Data-Mining-with-Python
Branch: master
Commit: 9fdae2873df3
Files: 32
Total size: 14.3 MB
Directory structure:
gitextract_qbrouktj/
├── Chapter 1/
│ ├── affinity_dataset.txt
│ ├── ch1_affinity.ipynb
│ ├── ch1_affinity_create.ipynb
│ └── ch1_oner_application.ipynb
├── Chapter 10/
│ └── Chapter 10 Clusterer.ipynb
├── Chapter 11/
│ ├── Chapter 11 (CIFAR).ipynb
│ └── Chapter 11 (Theano and Lasagne).ipynb
├── Chapter 12/
│ ├── CH12 MapReduce Basics.ipynb
│ ├── Chapter 12 (NB Predict).ipynb
│ ├── Chapter 12 (Test load).ipynb
│ ├── extract_posts.py
│ ├── nb_predict.py
│ └── nb_train.py
├── Chapter 2/
│ └── Ionosphere Nearest Neighbour.ipynb
├── Chapter 3/
│ └── Basketball Results.ipynb
├── Chapter 4/
│ └── ch4 Affinity Analysis.ipynb
├── Chapter 5/
│ ├── adult_tests.py
│ ├── ch5_adult.ipynb
│ └── ch5_advertisements.ipynb
├── Chapter 6/
│ ├── ch6_classify_twitter.ipynb
│ ├── ch6_get_twitter.ipynb
│ ├── ch6_label_twitter.ipynb
│ └── replicable_dataset.json
├── Chapter 7/
│ ├── CH7 From Load.ipynb
│ ├── ch7_collect_twitter_data.ipynb
│ └── ch7_part2_twitter.ipynb
├── Chapter 8/
│ ├── CH8 Rewrite.ipynb
│ └── Sigmoid.ipynb
├── Chapter 9/
│ ├── Chapter 9 Authorship Analysis.ipynb
│ └── getdata.py
├── LICENSE
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: Chapter 1/affinity_dataset.txt
================================================
0 0 1 1 1
1 1 0 1 0
1 0 1 1 0
0 0 1 1 1
0 1 0 0 1
0 1 0 0 0
1 0 0 0 1
1 0 0 0 1
0 0 0 1 1
0 0 1 1 1
1 1 0 0 1
0 1 0 0 0
0 0 0 0 1
0 0 1 0 1
0 1 0 0 1
0 0 1 1 1
1 0 0 0 1
0 0 1 1 1
1 1 0 0 0
0 1 0 0 0
0 0 1 0 0
0 1 0 0 1
0 1 0 0 0
0 1 0 0 1
0 0 1 1 1
0 0 1 1 0
0 0 1 0 1
0 0 0 0 1
0 1 0 0 0
0 1 0 1 0
1 1 1 0 1
1 1 0 0 1
0 0 1 1 1
0 0 1 0 1
0 0 1 1 1
0 0 1 1 0
0 1 1 0 1
0 0 1 1 0
0 1 0 0 1
0 0 0 0 1
0 0 1 0 1
1 1 0 1 1
1 0 0 0 1
0 0 1 1 1
0 1 0 0 0
0 1 0 1 1
0 1 0 0 0
0 1 0 0 0
0 0 1 1 0
0 0 1 1 1
0 1 0 1 0
0 1 1 0 0
0 0 1 1 0
0 0 1 1 1
1 0 0 0 0
0 1 0 1 0
1 0 0 0 1
0 1 0 0 0
0 0 0 0 1
0 0 1 1 1
0 1 1 1 1
1 1 0 0 0
0 0 1 0 1
1 0 0 0 1
1 1 0 0 0
0 1 1 0 0
0 0 0 0 1
0 1 0 0 0
0 0 1 1 1
0 1 0 0 1
1 0 0 0 1
1 0 0 0 1
0 1 0 0 1
0 0 1 1 1
1 0 1 0 1
1 1 0 0 1
0 1 0 0 1
1 1 1 0 1
0 0 1 1 1
1 0 0 0 0
0 0 1 1 1
1 1 0 1 0
0 0 1 0 0
0 0 1 0 1
0 1 0 0 0
1 1 0 0 0
0 0 0 1 0
0 0 0 1 1
0 1 0 0 0
0 1 0 0 0
1 1 0 0 1
0 0 1 0 0
0 1 0 0 1
1 1 0 1 0
1 0 0 0 1
0 1 0 0 0
0 0 1 1 0
0 1 1 0 0
0 0 1 1 0
0 0 0 0 1
================================================
FILE: Chapter 1/ch1_affinity.ipynb
================================================
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"This dataset has 100 samples and 5 features\n"
]
}
],
"source": [
"import numpy as np\n",
"dataset_filename = \"affinity_dataset.txt\"\n",
"X = np.loadtxt(dataset_filename)\n",
"n_samples, n_features = X.shape\n",
"print(\"This dataset has {0} samples and {1} features\".format(n_samples, n_features))"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[ 0. 0. 1. 1. 1.]\n",
" [ 1. 1. 0. 1. 0.]\n",
" [ 1. 0. 1. 1. 0.]\n",
" [ 0. 0. 1. 1. 1.]\n",
" [ 0. 1. 0. 0. 1.]]\n"
]
}
],
"source": [
"print(X[:5])"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# The names of the features, for your reference.\n",
"features = [\"bread\", \"milk\", \"cheese\", \"apples\", \"bananas\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In our first example, we will compute the Support and Confidence of the rule \"If a person buys Apples, they also buy Bananas\"."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"36 people bought Apples\n"
]
}
],
"source": [
"# First, how many rows contain our premise: that a person is buying apples\n",
"num_apple_purchases = 0\n",
"for sample in X:\n",
" if sample[3] == 1: # This person bought Apples\n",
" num_apple_purchases += 1\n",
"print(\"{0} people bought Apples\".format(num_apple_purchases))"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"21 cases of the rule being valid were discovered\n",
"15 cases of the rule being invalid were discovered\n"
]
}
],
"source": [
"# How many of the cases that a person bought Apples involved the people purchasing Bananas too?\n",
"# Record both cases where the rule is valid and is invalid.\n",
"rule_valid = 0\n",
"rule_invalid = 0\n",
"for sample in X:\n",
" if sample[3] == 1: # This person bought Apples\n",
" if sample[4] == 1:\n",
" # This person bought both Apples and Bananas\n",
" rule_valid += 1\n",
" else:\n",
" # This person bought Apples, but not Bananas\n",
" rule_invalid += 1\n",
"print(\"{0} cases of the rule being valid were discovered\".format(rule_valid))\n",
"print(\"{0} cases of the rule being invalid were discovered\".format(rule_invalid))"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The support is 21 and the confidence is 0.583.\n",
"As a percentage, that is 58.3%.\n"
]
}
],
"source": [
"# Now we have all the information needed to compute Support and Confidence\n",
"support = rule_valid # The Support is the number of times the rule is discovered.\n",
"confidence = rule_valid / num_apple_purchases\n",
"print(\"The support is {0} and the confidence is {1:.3f}.\".format(support, confidence))\n",
"# Confidence can be thought of as a percentage using the following:\n",
"print(\"As a percentage, that is {0:.1f}%.\".format(100 * confidence))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from collections import defaultdict\n",
"# Now compute for all possible rules\n",
"valid_rules = defaultdict(int)\n",
"invalid_rules = defaultdict(int)\n",
"num_occurences = defaultdict(int)\n",
"\n",
"for sample in X:\n",
" for premise in range(n_features):\n",
" if sample[premise] == 0: continue\n",
" # Record that the premise was bought in another transaction\n",
" num_occurences[premise] += 1\n",
" for conclusion in range(n_features):\n",
" if premise == conclusion: # It makes little sense to measure if X -> X.\n",
" continue\n",
" if sample[conclusion] == 1:\n",
" # This person also bought the conclusion item\n",
" valid_rules[(premise, conclusion)] += 1\n",
" else:\n",
" # This person bought the premise, but not the conclusion\n",
" invalid_rules[(premise, conclusion)] += 1\n",
"support = valid_rules\n",
"confidence = defaultdict(float)\n",
"for premise, conclusion in valid_rules.keys():\n",
" confidence[(premise, conclusion)] = valid_rules[(premise, conclusion)] / num_occurences[premise]"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Rule: If a person buys bread they will also buy milk\n",
" - Confidence: 0.519\n",
" - Support: 14\n",
"\n",
"Rule: If a person buys milk they will also buy cheese\n",
" - Confidence: 0.152\n",
" - Support: 7\n",
"\n",
"Rule: If a person buys apples they will also buy cheese\n",
" - Confidence: 0.694\n",
" - Support: 25\n",
"\n",
"Rule: If a person buys milk they will also buy apples\n",
" - Confidence: 0.196\n",
" - Support: 9\n",
"\n",
"Rule: If a person buys bread they will also buy apples\n",
" - Confidence: 0.185\n",
" - Support: 5\n",
"\n",
"Rule: If a person buys apples they will also buy bread\n",
" - Confidence: 0.139\n",
" - Support: 5\n",
"\n",
"Rule: If a person buys apples they will also buy bananas\n",
" - Confidence: 0.583\n",
" - Support: 21\n",
"\n",
"Rule: If a person buys apples they will also buy milk\n",
" - Confidence: 0.250\n",
" - Support: 9\n",
"\n",
"Rule: If a person buys milk they will also buy bananas\n",
" - Confidence: 0.413\n",
" - Support: 19\n",
"\n",
"Rule: If a person buys cheese they will also buy bananas\n",
" - Confidence: 0.659\n",
" - Support: 27\n",
"\n",
"Rule: If a person buys cheese they will also buy bread\n",
" - Confidence: 0.098\n",
" - Support: 4\n",
"\n",
"Rule: If a person buys cheese they will also buy apples\n",
" - Confidence: 0.610\n",
" - Support: 25\n",
"\n",
"Rule: If a person buys cheese they will also buy milk\n",
" - Confidence: 0.171\n",
" - Support: 7\n",
"\n",
"Rule: If a person buys bananas they will also buy apples\n",
" - Confidence: 0.356\n",
" - Support: 21\n",
"\n",
"Rule: If a person buys bread they will also buy bananas\n",
" - Confidence: 0.630\n",
" - Support: 17\n",
"\n",
"Rule: If a person buys bananas they will also buy cheese\n",
" - Confidence: 0.458\n",
" - Support: 27\n",
"\n",
"Rule: If a person buys milk they will also buy bread\n",
" - Confidence: 0.304\n",
" - Support: 14\n",
"\n",
"Rule: If a person buys bananas they will also buy milk\n",
" - Confidence: 0.322\n",
" - Support: 19\n",
"\n",
"Rule: If a person buys bread they will also buy cheese\n",
" - Confidence: 0.148\n",
" - Support: 4\n",
"\n",
"Rule: If a person buys bananas they will also buy bread\n",
" - Confidence: 0.288\n",
" - Support: 17\n",
"\n"
]
}
],
"source": [
"for premise, conclusion in confidence:\n",
" premise_name = features[premise]\n",
" conclusion_name = features[conclusion]\n",
" print(\"Rule: If a person buys {0} they will also buy {1}\".format(premise_name, conclusion_name))\n",
" print(\" - Confidence: {0:.3f}\".format(confidence[(premise, conclusion)]))\n",
" print(\" - Support: {0}\".format(support[(premise, conclusion)]))\n",
" print(\"\")"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def print_rule(premise, conclusion, support, confidence, features):\n",
" premise_name = features[premise]\n",
" conclusion_name = features[conclusion]\n",
" print(\"Rule: If a person buys {0} they will also buy {1}\".format(premise_name, conclusion_name))\n",
" print(\" - Confidence: {0:.3f}\".format(confidence[(premise, conclusion)]))\n",
" print(\" - Support: {0}\".format(support[(premise, conclusion)]))\n",
" print(\"\")"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Rule: If a person buys milk they will also buy apples\n",
" - Confidence: 0.196\n",
" - Support: 9\n",
"\n"
]
}
],
"source": [
"premise = 1\n",
"conclusion = 3\n",
"print_rule(premise, conclusion, support, confidence, features)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[((0, 1), 14),\n",
" ((1, 2), 7),\n",
" ((3, 2), 25),\n",
" ((1, 3), 9),\n",
" ((0, 2), 4),\n",
" ((3, 0), 5),\n",
" ((4, 1), 19),\n",
" ((3, 1), 9),\n",
" ((1, 4), 19),\n",
" ((2, 4), 27),\n",
" ((2, 0), 4),\n",
" ((2, 3), 25),\n",
" ((2, 1), 7),\n",
" ((4, 3), 21),\n",
" ((0, 4), 17),\n",
" ((4, 2), 27),\n",
" ((1, 0), 14),\n",
" ((3, 4), 21),\n",
" ((0, 3), 5),\n",
" ((4, 0), 17)]\n"
]
}
],
"source": [
"# Sort by support\n",
"from pprint import pprint\n",
"pprint(list(support.items()))"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from operator import itemgetter\n",
"sorted_support = sorted(support.items(), key=itemgetter(1), reverse=True)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Rule #1\n",
"Rule: If a person buys cheese they will also buy bananas\n",
" - Confidence: 0.659\n",
" - Support: 27\n",
"\n",
"Rule #2\n",
"Rule: If a person buys bananas they will also buy cheese\n",
" - Confidence: 0.458\n",
" - Support: 27\n",
"\n",
"Rule #3\n",
"Rule: If a person buys apples they will also buy cheese\n",
" - Confidence: 0.694\n",
" - Support: 25\n",
"\n",
"Rule #4\n",
"Rule: If a person buys cheese they will also buy apples\n",
" - Confidence: 0.610\n",
" - Support: 25\n",
"\n",
"Rule #5\n",
"Rule: If a person buys bananas they will also buy apples\n",
" - Confidence: 0.356\n",
" - Support: 21\n",
"\n"
]
}
],
"source": [
"for index in range(5):\n",
" print(\"Rule #{0}\".format(index + 1))\n",
" (premise, conclusion) = sorted_support[index][0]\n",
" print_rule(premise, conclusion, support, confidence, features)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"sorted_confidence = sorted(confidence.items(), key=itemgetter(1), reverse=True)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Rule #1\n",
"Rule: If a person buys apples they will also buy cheese\n",
" - Confidence: 0.694\n",
" - Support: 25\n",
"\n",
"Rule #2\n",
"Rule: If a person buys cheese they will also buy bananas\n",
" - Confidence: 0.659\n",
" - Support: 27\n",
"\n",
"Rule #3\n",
"Rule: If a person buys bread they will also buy bananas\n",
" - Confidence: 0.630\n",
" - Support: 17\n",
"\n",
"Rule #4\n",
"Rule: If a person buys cheese they will also buy apples\n",
" - Confidence: 0.610\n",
" - Support: 25\n",
"\n",
"Rule #5\n",
"Rule: If a person buys apples they will also buy bananas\n",
" - Confidence: 0.583\n",
" - Support: 21\n",
"\n"
]
}
],
"source": [
"for index in range(5):\n",
" print(\"Rule #{0}\".format(index + 1))\n",
" (premise, conclusion) = sorted_confidence[index][0]\n",
" print_rule(premise, conclusion, support, confidence, features)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.4.0"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
================================================
FILE: Chapter 1/ch1_affinity_create.ipynb
================================================
{
"metadata": {
"name": ""
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "code",
"collapsed": false,
"input": [
"import numpy as np"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 1
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"X = np.zeros((100, 5), dtype='bool')\n",
"features = [\"bread\", \"milk\", \"cheese\", \"apples\", \"bananas\"]"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 2
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for i in range(X.shape[0]):\n",
" if np.random.random() < 0.3:\n",
" # A bread winner\n",
" X[i][0] = 1\n",
" if np.random.random() < 0.5:\n",
" # Who likes milk\n",
" X[i][1] = 1\n",
" if np.random.random() < 0.2:\n",
" # Who likes cheese\n",
" X[i][2] = 1\n",
" if np.random.random() < 0.25:\n",
" # Who likes apples\n",
" X[i][3] = 1\n",
" if np.random.random() < 0.5:\n",
" # Who likes bananas\n",
" X[i][4] = 1\n",
" else:\n",
" # Not a bread winner\n",
" if np.random.random() < 0.5:\n",
" # Who likes milk\n",
" X[i][1] = 1\n",
" if np.random.random() < 0.2:\n",
" # Who likes cheese\n",
" X[i][2] = 1\n",
" if np.random.random() < 0.25:\n",
" # Who likes apples\n",
" X[i][3] = 1\n",
" if np.random.random() < 0.5:\n",
" # Who likes bananas\n",
" X[i][4] = 1\n",
" else:\n",
" if np.random.random() < 0.8:\n",
" # Who likes cheese\n",
" X[i][2] = 1\n",
" if np.random.random() < 0.6:\n",
" # Who likes apples\n",
" X[i][3] = 1\n",
" if np.random.random() < 0.7:\n",
" # Who likes bananas\n",
" X[i][4] = 1\n",
" if X[i].sum() == 0:\n",
" X[i][4] = 1 # Must buy something, so gets bananas\n"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 3
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print(X[:5])"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[[False False True True True]\n",
" [ True True False True False]\n",
" [ True False True True False]\n",
" [False False True True True]\n",
" [False True False False True]]\n"
]
}
],
"prompt_number": 5
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"np.savetxt(\"affinity_dataset.txt\", X, fmt='%d')"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 7
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": []
}
],
"metadata": {}
}
]
}
================================================
FILE: Chapter 1/ch1_oner_application.ipynb
================================================
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The OneR algorithm is quite simple but can be quite effective, showing the power of using even basic statistics in many applications.\n",
"The algorithm is:\n",
"\n",
"* For each variable\n",
" * For each value of the variable\n",
" * The prediction based on this variable goes the most frequent class\n",
" * Compute the error of this prediction\n",
" * Sum the prediction errors for all values of the variable\n",
"* Use the variable with the lowest error"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Iris Plants Database\n",
"\n",
"Notes\n",
"-----\n",
"Data Set Characteristics:\n",
" :Number of Instances: 150 (50 in each of three classes)\n",
" :Number of Attributes: 4 numeric, predictive attributes and the class\n",
" :Attribute Information:\n",
" - sepal length in cm\n",
" - sepal width in cm\n",
" - petal length in cm\n",
" - petal width in cm\n",
" - class:\n",
" - Iris-Setosa\n",
" - Iris-Versicolour\n",
" - Iris-Virginica\n",
" :Summary Statistics:\n",
" ============== ==== ==== ======= ===== ====================\n",
" Min Max Mean SD Class Correlation\n",
" ============== ==== ==== ======= ===== ====================\n",
" sepal length: 4.3 7.9 5.84 0.83 0.7826\n",
" sepal width: 2.0 4.4 3.05 0.43 -0.4194\n",
" petal length: 1.0 6.9 3.76 1.76 0.9490 (high!)\n",
" petal width: 0.1 2.5 1.20 0.76 0.9565 (high!)\n",
" ============== ==== ==== ======= ===== ====================\n",
" :Missing Attribute Values: None\n",
" :Class Distribution: 33.3% for each of 3 classes.\n",
" :Creator: R.A. Fisher\n",
" :Donor: Michael Marshall (MARSHALL%PLU@io.arc.nasa.gov)\n",
" :Date: July, 1988\n",
"\n",
"This is a copy of UCI ML iris datasets.\n",
"http://archive.ics.uci.edu/ml/datasets/Iris\n",
"\n",
"The famous Iris database, first used by Sir R.A Fisher\n",
"\n",
"This is perhaps the best known database to be found in the\n",
"pattern recognition literature. Fisher's paper is a classic in the field and\n",
"is referenced frequently to this day. (See Duda & Hart, for example.) The\n",
"data set contains 3 classes of 50 instances each, where each class refers to a\n",
"type of iris plant. One class is linearly separable from the other 2; the\n",
"latter are NOT linearly separable from each other.\n",
"\n",
"References\n",
"----------\n",
" - Fisher,R.A. \"The use of multiple measurements in taxonomic problems\"\n",
" Annual Eugenics, 7, Part II, 179-188 (1936); also in \"Contributions to\n",
" Mathematical Statistics\" (John Wiley, NY, 1950).\n",
" - Duda,R.O., & Hart,P.E. (1973) Pattern Classification and Scene Analysis.\n",
" (Q327.D83) John Wiley & Sons. ISBN 0-471-22361-1. See page 218.\n",
" - Dasarathy, B.V. (1980) \"Nosing Around the Neighborhood: A New System\n",
" Structure and Classification Rule for Recognition in Partially Exposed\n",
" Environments\". IEEE Transactions on Pattern Analysis and Machine\n",
" Intelligence, Vol. PAMI-2, No. 1, 67-71.\n",
" - Gates, G.W. (1972) \"The Reduced Nearest Neighbor Rule\". IEEE Transactions\n",
" on Information Theory, May 1972, 431-433.\n",
" - See also: 1988 MLC Proceedings, 54-64. Cheeseman et al\"s AUTOCLASS II\n",
" conceptual clustering system finds 3 classes in the data.\n",
" - Many, many more ...\n",
"\n"
]
}
],
"source": [
"# Load our dataset\n",
"from sklearn.datasets import load_iris\n",
"#X, y = np.loadtxt(\"X_classification.txt\"), np.loadtxt(\"y_classification.txt\")\n",
"dataset = load_iris()\n",
"X = dataset.data\n",
"y = dataset.target\n",
"print(dataset.DESCR)\n",
"n_samples, n_features = X.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Our attributes are continuous, while we want categorical features to use OneR. We will perform a *preprocessing* step called discretisation. At this stage, we will perform a simple procedure: compute the mean and determine whether a value is above or below the mean."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Compute the mean for each attribute\n",
"attribute_means = X.mean(axis=0)\n",
"assert attribute_means.shape == (n_features,)\n",
"X_d = np.array(X >= attribute_means, dtype='int')"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"There are (112,) training samples\n",
"There are (38,) testing samples\n"
]
}
],
"source": [
"# Now, we split into a training and test set\n",
"from sklearn.cross_validation import train_test_split\n",
"\n",
"# Set the random state to the same number to get the same results as in the book\n",
"random_state = 14\n",
"\n",
"X_train, X_test, y_train, y_test = train_test_split(X_d, y, random_state=random_state)\n",
"print(\"There are {} training samples\".format(y_train.shape))\n",
"print(\"There are {} testing samples\".format(y_test.shape))"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from collections import defaultdict\n",
"from operator import itemgetter\n",
"\n",
"\n",
"def train(X, y_true, feature):\n",
" \"\"\"Computes the predictors and error for a given feature using the OneR algorithm\n",
" \n",
" Parameters\n",
" ----------\n",
" X: array [n_samples, n_features]\n",
" The two dimensional array that holds the dataset. Each row is a sample, each column\n",
" is a feature.\n",
" \n",
" y_true: array [n_samples,]\n",
" The one dimensional array that holds the class values. Corresponds to X, such that\n",
" y_true[i] is the class value for sample X[i].\n",
" \n",
" feature: int\n",
" An integer corresponding to the index of the variable we wish to test.\n",
" 0 <= variable < n_features\n",
" \n",
" Returns\n",
" -------\n",
" predictors: dictionary of tuples: (value, prediction)\n",
" For each item in the array, if the variable has a given value, make the given prediction.\n",
" \n",
" error: float\n",
" The ratio of training data that this rule incorrectly predicts.\n",
" \"\"\"\n",
" # Check that variable is a valid number\n",
" n_samples, n_features = X.shape\n",
" assert 0 <= feature < n_features\n",
" # Get all of the unique values that this variable has\n",
" values = set(X[:,feature])\n",
" # Stores the predictors array that is returned\n",
" predictors = dict()\n",
" errors = []\n",
" for current_value in values:\n",
" most_frequent_class, error = train_feature_value(X, y_true, feature, current_value)\n",
" predictors[current_value] = most_frequent_class\n",
" errors.append(error)\n",
" # Compute the total error of using this feature to classify on\n",
" total_error = sum(errors)\n",
" return predictors, total_error\n",
"\n",
"# Compute what our predictors say each sample is based on its value\n",
"#y_predicted = np.array([predictors[sample[feature]] for sample in X])\n",
" \n",
"\n",
"def train_feature_value(X, y_true, feature, value):\n",
" # Create a simple dictionary to count how frequency they give certain predictions\n",
" class_counts = defaultdict(int)\n",
" # Iterate through each sample and count the frequency of each class/value pair\n",
" for sample, y in zip(X, y_true):\n",
" if sample[feature] == value:\n",
" class_counts[y] += 1\n",
" # Now get the best one by sorting (highest first) and choosing the first item\n",
" sorted_class_counts = sorted(class_counts.items(), key=itemgetter(1), reverse=True)\n",
" most_frequent_class = sorted_class_counts[0][0]\n",
" # The error is the number of samples that do not classify as the most frequent class\n",
" # *and* have the feature value.\n",
" n_samples = X.shape[1]\n",
" error = sum([class_count for class_value, class_count in class_counts.items()\n",
" if class_value != most_frequent_class])\n",
" return most_frequent_class, error"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The best model is based on variable 2 and has error 37.00\n",
"{'variable': 2, 'predictor': {0: 0, 1: 2}}\n"
]
}
],
"source": [
"# Compute all of the predictors\n",
"all_predictors = {variable: train(X_train, y_train, variable) for variable in range(X_train.shape[1])}\n",
"errors = {variable: error for variable, (mapping, error) in all_predictors.items()}\n",
"# Now choose the best and save that as \"model\"\n",
"# Sort by error\n",
"best_variable, best_error = sorted(errors.items(), key=itemgetter(1))[0]\n",
"print(\"The best model is based on variable {0} and has error {1:.2f}\".format(best_variable, best_error))\n",
"\n",
"# Choose the bset model\n",
"model = {'variable': best_variable,\n",
" 'predictor': all_predictors[best_variable][0]}\n",
"print(model)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def predict(X_test, model):\n",
" variable = model['variable']\n",
" predictor = model['predictor']\n",
" y_predicted = np.array([predictor[int(sample[variable])] for sample in X_test])\n",
" return y_predicted"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0 0 0 2 2 2 0 2 0 2 2 0 2 2 0 2 0 2 2 2 0 0 0 2 0 2 0 2 2 0 0 0 2 0 2 0 2\n",
" 2]\n"
]
}
],
"source": [
"y_predicted = predict(X_test, model)\n",
"print(y_predicted)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The test accuracy is 65.8%\n"
]
}
],
"source": [
"# Compute the accuracy by taking the mean of the amounts that y_predicted is equal to y_test\n",
"accuracy = np.mean(y_predicted == y_test) * 100\n",
"print(\"The test accuracy is {:.1f}%\".format(accuracy))"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from sklearn.metrics import classification_report"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" precision recall f1-score support\n",
"\n",
" 0 0.94 1.00 0.97 17\n",
" 1 0.00 0.00 0.00 13\n",
" 2 0.40 1.00 0.57 8\n",
"\n",
"avg / total 0.51 0.66 0.55 38\n",
"\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/usr/local/lib/python3.4/dist-packages/sklearn/metrics/metrics.py:1771: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples.\n",
" 'precision', 'predicted', average, warn_for)\n"
]
}
],
"source": [
"print(classification_report(y_test, y_predicted))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.4.0"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
================================================
FILE: Chapter 10/Chapter 10 Clusterer.ipynb
================================================
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"490"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import os\n",
"import numpy as np\n",
"data_folder = os.path.join(os.path.expanduser(\"~\"), \"Data\", \"websites\", \"textonly\")\n",
"\n",
"documents = [open(os.path.join(data_folder, filename)).read() for filename in os.listdir(data_folder)]\n",
"len(documents)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Pretty printing has been turned OFF\n"
]
}
],
"source": [
"pprint([document[:100] for document in documents[:5]])"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from sklearn.cluster import KMeans\n",
"from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from sklearn.pipeline import Pipeline\n",
"\n",
"n_clusters = 10\n",
"\n",
"pipeline = Pipeline([('feature_extraction', TfidfVectorizer(max_df=0.4)),\n",
" ('clusterer', KMeans(n_clusters=n_clusters))\n",
" ])"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Pipeline(steps=[('feature_extraction', TfidfVectorizer(analyzer='word', binary=False, charset=None,\n",
" charset_error=None, decode_error='strict',\n",
" dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',\n",
" lowercase=True, max_df=0.4, max_features=None, min_df=1,\n",
" ngram_range=(... n_init=10,\n",
" n_jobs=1, precompute_distances=True, random_state=None, tol=0.0001,\n",
" verbose=0))])"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pipeline.fit(documents)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"labels = pipeline.predict(documents)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Cluster 0 contains 1 samples\n",
"Cluster 1 contains 2 samples\n",
"Cluster 2 contains 439 samples\n",
"Cluster 3 contains 1 samples\n",
"Cluster 4 contains 2 samples\n",
"Cluster 5 contains 3 samples\n",
"Cluster 6 contains 27 samples\n",
"Cluster 7 contains 2 samples\n",
"Cluster 8 contains 12 samples\n",
"Cluster 9 contains 1 samples\n"
]
}
],
"source": [
"from collections import Counter\n",
"c = Counter(labels)\n",
"for cluster_number in range(n_clusters):\n",
" print(\"Cluster {} contains {} samples\".format(cluster_number, c[cluster_number]))"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"c[0]"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"381.97317261989065"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pipeline.named_steps['clusterer'].inertia_"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"inertia_scores = []\n",
"n_cluster_values = list(range(2, 20))\n",
"for n_clusters in n_cluster_values:\n",
" cur_inertia_scores = []\n",
" X = TfidfVectorizer(max_df=0.4).fit_transform(documents)\n",
" for i in range(30):\n",
" km = KMeans(n_clusters=n_clusters).fit(X)\n",
" cur_inertia_scores.append(km.inertia_)\n",
" inertia_scores.append(cur_inertia_scores)\n",
"inertia_scores = np.array(inertia_scores)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAACOEAAAR9CAYAAAAam8EUAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3XuQr3dB3/H3OUEGCXdRAsglUZGbRQRBVOSQoDAgt4IF\nhZQQKlitRMSM0BmGr1LEOhVoZ8pMx3hH0NYWzA3vHCgXrSiIgFRlpnUS4JxIoVaDCYTtH7vAEZKc\n88tvd7/77L5eMzv7/J7z29/z+Sv7x77zPAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+9pp1burS7Ze36H6neovqt+ubnfCe19c/WX1\nweo7dnEjAAAAAAAAAABMcfgU33dB9YFqY+v1i9qMcO5V/d7W66r7Vk/b+v6Y6jUrXAMAAAAAAAAA\nAPatr6x+t3pkn78TzgerO20dn7H1ujbvgvOjJ/zsb1bftAsbAQAAAAAAAABgmlO5S82rqgurz5xw\n7k7Vsa3jY30+yLlLdcUJ77uiuuuaGwEAAAAAAAAAYE87WYTzndXx6t3VoRt4z0aff0zVDf07AAAA\nAAAAAADsWzc7yb9/c/WE6rHVLarbVL/c5t1vzqg+Wt25zVCn6srqbif8/FdunftCf1V91U1eDQAA\nAAAAAAAAO+tD1VfvxAc/orpk6/inqh/dOn5R9ZNbx/et3lPdvDpza8z13UHH3XEAgKUYswcAAJyi\nMXsAAMApGrMHAACcopX6lpPdCeeGPvwnq/9cPaf6X9U/2zr/ga3zH6g+XX3/qoMAAAAAAAAAAIBT\nI8wBAJZizB4AAHCKxuwBAACnaMweAABwilbqWw7v1AoAgH3i6OwBAACn6OjsAQAAp+jo7AEAAPuJ\nO+EAAAAAAAAAALCXuRMOAAAAAAAAAADsJhEOAAAAAAAAAACsSYQDAAAAAAAAAABrEuEAAAAAAAAA\nAMCaRDgAAAAAAAAAALAmEQ4AAAAAAAAAAKxJhAMAAAAAAAAAAGsS4QAAAAAAAAAAwJpEOAAAAAAA\nAAAAsCYRDgAAAAAAAAAArEmEAwAAAAAAAAAAaxLhAAAAAAAAAADAmkQ4AAAAAAAAAACwJhEOAAAA\nAAAAAACsSYQDAAAAAAAAAABrEuEAAAAAAAAAAMCaRDgAAAAAAAAAALAmEQ4AAAAAAAAAAKxJhAMA\nAAAAAAAAAGsS4QAAAAAAAAAAwJpEOAAAAAAAAAAAsCYRDgAAAAAAAAAArEmEAwAAAAAAAAAAaxLh\nAAAAAAAAAADAmkQ4AAAAAAAAAACwJhEOAAAAAAAAAACsSYQDAAAAAAAAAABrEuEAAAAAAAAAAMCa\nRDgAAAAAAAAAALAmEQ4AAAAAAAAAAKxJhAMAAAAAAAAAAGsS4QAAAAAAAAAAwJpEOAAAAAAAAAAA\nsCYRDgAAAAAAAAAArEmEAwAAAAAAAAAAaxLhAAAAAAAAAADAmkQ4AAAAAAAAAACwJhEOAAAAAAAA\nAACsSYQDAAAAAAAAAABrEuEAAAAAAAAAAMCaRDgAAAAAAAAAALAmEQ4AAAAAAAAAAKxJhAMAAAAA\nAAAAAGsS4QAAAAAAAAAAwJpEOAAAAAAAAAAAsCYRDgAAAAAAAAAArEmEAwAAAAAAAAAAaxLhAAAA\nAAAAAADAmkQ4AAAAAAAAAACwJhEOAAAAAAAAAACsSYQDAAAAAAAAAABrEuEAAAAAAAAAAMCaRDgA\nAAAAAAAAALAmEQ4AAAAAAAAAAKxJhAMAAAAAAAAAAGsS4QAAAAAAAAAAwJpEOAAAAAAAAAAAsCYR\nDgAAAAAAAAAArEmEAwAAAAAAAAAAaxLhAAAAAAAAAADAmkQ4AAAAAAAAAACwJhEOAAAAAAAAAACs\nSYQDAAAAAAAAAABrEuEAAAAAAAAAAMCaRDgAAAAAAAAAALAmEQ4AAAAAAAAAAKxJhAMAAAAAAAAA\nAGsS4QAAAAAAAAAAwJpEOAAAAAAAAAAAsCYRDgAAAAAAAAAArEmEAwAAAAAAAAAAaxLhAAAAAAAA\nAADAmkQ4AAAAAAAAAACwJhEOAAAAAAAAAACsSYQDAAAAAAAAAABrEuEAAAAAAAAAAMCaRDgAAAAA\nAAAAALAmEQ4AAAAAAAAAAKxJhAMAAAAAAAAAAGsS4QAAAAAAAAAAwJpEOAAAAAAAAAAAsCYRDgAA\nAAAAAAAArEmEAwAAAAAAAAAAaxLhAAAAAAAAAADAmkQ4AAAAAAAAAACwJhEOAAAAAAAAAACsSYQD\nAAAAAAAAAABrEuEAAAAAAAAAAMCaRDgAAAAAAAAAALAmEQ4AAAAAAAAAAKxJhAMAAAAAAAAAAGsS\n4QAAAAAAAAAAwJpEOAAAAAAAAAAAsCYRDgAAAAAAAAAArEmEAwAAAAAAAAAAaxLhAAAAAAAAAADA\n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\n",
"text/plain": [
"<matplotlib.figure.Figure object at 0x7f0bc5ae9240>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%matplotlib inline\n",
"from matplotlib import pyplot as plt\n",
"\n",
"inertia_means = np.mean(inertia_scores, axis=1)\n",
"inertia_stderr = np.std(inertia_scores, axis=1)\n",
"\n",
"fig = plt.figure(figsize=(40,20))\n",
"plt.errorbar(n_cluster_values, inertia_means, inertia_stderr, color='green')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Pipeline(steps=[('feature_extraction', TfidfVectorizer(analyzer='word', binary=False, charset=None,\n",
" charset_error=None, decode_error='strict',\n",
" dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',\n",
" lowercase=True, max_df=0.4, max_features=None, min_df=1,\n",
" ngram_range=(... n_init=10,\n",
" n_jobs=1, precompute_distances=True, random_state=None, tol=0.0001,\n",
" verbose=0))])"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"n_clusters = 6\n",
"\n",
"pipeline = Pipeline([('feature_extraction', TfidfVectorizer(max_df=0.4)),\n",
" ('clusterer', KMeans(n_clusters=n_clusters))\n",
" ])\n",
"pipeline.fit(documents)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"labels = pipeline.predict(documents)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Cluster 0 contains 21 samples\n",
" Most important terms\n",
" 1) korea (score: 0.1591)\n",
" 2) korean (score: 0.1573)\n",
" 3) south (score: 0.1336)\n",
" 4) kim (score: 0.1088)\n",
" 5) north (score: 0.1077)\n",
"\n",
"Cluster 1 contains 33 samples\n",
" Most important terms\n",
" 1) iran (score: 0.1047)\n",
" 2) netanyahu (score: 0.0869)\n",
" 3) nuclear (score: 0.0660)\n",
" 4) he (score: 0.0615)\n",
" 5) his (score: 0.0550)\n",
"\n",
"Cluster 2 contains 156 samples\n",
" Most important terms\n",
" 1) palestinian (score: 0.0196)\n",
" 2) israel (score: 0.0138)\n",
" 3) security (score: 0.0118)\n",
" 4) bank (score: 0.0115)\n",
" 5) its (score: 0.0103)\n",
"\n",
"Cluster 3 contains 31 samples\n",
" Most important terms\n",
" 1) browser (score: 0.2786)\n",
" 2) able (score: 0.2429)\n",
" 3) you (score: 0.2018)\n",
" 4) css (score: 0.1925)\n",
" 5) sheets (score: 0.1925)\n",
"\n",
"Cluster 4 contains 48 samples\n",
" Most important terms\n",
" 1) al (score: 0.0862)\n",
" 2) isis (score: 0.0723)\n",
" 3) islamic (score: 0.0664)\n",
" 4) iraq (score: 0.0657)\n",
" 5) state (score: 0.0580)\n",
"\n",
"Cluster 5 contains 201 samples\n",
" Most important terms\n",
" 1) he (score: 0.0448)\n",
" 2) we (score: 0.0306)\n",
" 3) they (score: 0.0294)\n",
" 4) his (score: 0.0254)\n",
" 5) who (score: 0.0253)\n",
"\n"
]
}
],
"source": [
"c = Counter(labels)\n",
"\n",
"terms = pipeline.named_steps['feature_extraction'].get_feature_names()\n",
"\n",
"for cluster_number in range(n_clusters):\n",
" print(\"Cluster {} contains {} samples\".format(cluster_number, c[cluster_number]))\n",
" print(\" Most important terms\")\n",
" centroid = pipeline.named_steps['clusterer'].cluster_centers_[cluster_number]\n",
" most_important = centroid.argsort()\n",
" for i in range(5):\n",
" term_index = most_important[-(i+1)]\n",
" print(\" {0}) {1} (score: {2:.4f})\".format(i+1, terms[term_index], centroid[term_index]))\n",
" print()"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.031820420989154712"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.metrics import silhouette_score\n",
"X = pipeline.named_steps['feature_extraction'].transform(documents)\n",
"silhouette_score(X, labels)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"14327"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(terms)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"Y = pipeline.transform(documents) "
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"km = KMeans(n_clusters=n_clusters)\n",
"labels = km.fit_predict(Y)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Cluster 0 contains 89 samples\n",
"Cluster 1 contains 65 samples\n",
"Cluster 2 contains 7 samples\n",
"Cluster 3 contains 24 samples\n",
"Cluster 4 contains 290 samples\n",
"Cluster 5 contains 15 samples\n"
]
}
],
"source": [
"c = Counter(labels)\n",
"for cluster_number in range(n_clusters):\n",
" print(\"Cluster {} contains {} samples\".format(cluster_number, c[cluster_number]))"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.56564461613141714"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"silhouette_score(Y, labels)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(490, 6)"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Y.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Evidence Accumulation Clustering"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from scipy.sparse import csr_matrix\n",
"\n",
"\n",
"def create_coassociation_matrix(labels):\n",
" rows = []\n",
" cols = []\n",
" unique_labels = set(labels)\n",
" for label in unique_labels:\n",
" indices = np.where(labels == label)[0]\n",
" for index1 in indices:\n",
" for index2 in indices:\n",
" rows.append(index1)\n",
" cols.append(index2)\n",
" data = np.ones((len(rows),))\n",
" return csr_matrix((data, (rows, cols)), dtype='float')\n"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"C = create_coassociation_matrix(labels)"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"<490x490 sparse matrix of type '<class 'numpy.float64'>'\n",
"\twith 97096 stored elements in Compressed Sparse Row format>"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"C"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"((490, 490), 240100)"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"C.shape, C.shape[0] * C.shape[1]"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.4043981674302374"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(C.nonzero()[0]) / (C.shape[0] * C.shape[1])"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from scipy.sparse.csgraph import minimum_spanning_tree"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"mst = minimum_spanning_tree(C)"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"<490x490 sparse matrix of type '<class 'numpy.float64'>'\n",
"\twith 484 stored elements in Compressed Sparse Row format>"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mst"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"pipeline = Pipeline([('feature_extraction', TfidfVectorizer(max_df=0.4)),\n",
" ('clusterer', KMeans(n_clusters=3))\n",
" ])\n",
"pipeline.fit(documents)\n",
"labels2 = pipeline.predict(documents)\n",
"C2 = create_coassociation_matrix(labels2)"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"matrix([[ 1. , 0.5, 0.5, ..., 0.5, 0.5, 0.5],\n",
" [ 0.5, 1. , 1. , ..., 1. , 1. , 1. ],\n",
" [ 0.5, 1. , 1. , ..., 1. , 1. , 1. ],\n",
" ..., \n",
" [ 0.5, 1. , 1. , ..., 1. , 1. , 1. ],\n",
" [ 0.5, 1. , 1. , ..., 1. , 1. , 1. ],\n",
" [ 0.5, 1. , 1. , ..., 1. , 1. , 1. ]])"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"C_sum = (C + C2) / 2\n",
"#C_sum.data = C_sum.data\n",
"C_sum.todense()"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"<490x490 sparse matrix of type '<class 'numpy.float64'>'\n",
"\twith 489 stored elements in Compressed Sparse Row format>"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mst = minimum_spanning_tree(-C_sum)\n",
"mst"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"<490x490 sparse matrix of type '<class 'numpy.float64'>'\n",
"\twith 481 stored elements in Compressed Sparse Row format>"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#mst.data[mst.data < 1] = 0\n",
"mst.data[mst.data > -1] = 0\n",
"mst.eliminate_zeros()\n",
"mst"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from scipy.sparse.csgraph import connected_components\n",
"number_of_clusters, labels = connected_components(mst)"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"\n",
"from sklearn.base import BaseEstimator, ClusterMixin\n",
"\n",
"class EAC(BaseEstimator, ClusterMixin):\n",
" def __init__(self, n_clusterings=10, cut_threshold=0.5, n_clusters_range=(3, 10)):\n",
" self.n_clusterings = n_clusterings\n",
" self.cut_threshold = cut_threshold\n",
" self.n_clusters_range = n_clusters_range\n",
" \n",
" def fit(self, X, y=None):\n",
" C = sum((create_coassociation_matrix(self._single_clustering(X))\n",
" for i in range(self.n_clusterings)))\n",
" mst = minimum_spanning_tree(-C)\n",
" mst.data[mst.data > -self.cut_threshold] = 0\n",
" mst.eliminate_zeros()\n",
" self.n_components, self.labels_ = connected_components(mst)\n",
" return self\n",
" \n",
" def _single_clustering(self, X):\n",
" n_clusters = np.random.randint(*self.n_clusters_range)\n",
" km = KMeans(n_clusters=n_clusters)\n",
" return km.fit_predict(X)\n",
" \n",
" def fit_predict(self, X):\n",
" self.fit(X)\n",
" return self.labels_"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"pipeline = Pipeline([('feature_extraction', TfidfVectorizer(max_df=0.4)),\n",
" ('clusterer', EAC())\n",
" ])"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Pipeline(steps=[('feature_extraction', TfidfVectorizer(analyzer='word', binary=False, charset=None,\n",
" charset_error=None, decode_error='strict',\n",
" dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',\n",
" lowercase=True, max_df=0.4, max_features=None, min_df=1,\n",
" ngram_range=(...ocabulary=None)), ('clusterer', EAC(cut_threshold=0.5, n_clusterings=10, n_clusters_range=(3, 10)))])"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pipeline.fit(documents)"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"labels = pipeline.named_steps['clusterer'].labels_"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"c = Counter(labels)"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Counter({0: 490})"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"c"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Online Learning"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from sklearn.cluster import MiniBatchKMeans"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"vec = TfidfVectorizer(max_df=0.4)"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"X = vec.fit_transform(documents)"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"mbkm = MiniBatchKMeans(random_state=14, n_clusters=3)\n",
"batch_size = 500\n",
"\n",
"indices = np.arange(0, X.shape[0])\n",
"for iteration in range(100):\n",
" sample = np.random.choice(indices, size=batch_size, replace=True)\n",
" mbkm.partial_fit(X[sample[:batch_size]])"
]
},
{
"cell_type": "code",
"execution_count": 74,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"mbkm = MiniBatchKMeans(random_state=14, n_clusters=3)\n",
"batch_size = 10\n",
"\n",
"for iteration in range(int(X.shape[0] / batch_size)):\n",
" start = batch_size * iteration\n",
" end = batch_size * (iteration + 1)\n",
" mbkm.partial_fit(X[start:end])"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"401.6913550000382"
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"labels_mbkm = mbkm.predict(X)\n",
"mbkm.inertia_"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"392.6561949236311"
]
},
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"km = KMeans(random_state=14, n_clusters=3)\n",
"labels_km = km.fit_predict(X)\n",
"km.inertia_"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from sklearn.metrics import adjusted_mutual_info_score, homogeneity_score\n",
"from sklearn.metrics import mutual_info_score, v_measure_score"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.39531764243316064"
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v_measure_score(labels_mbkm, labels_km)"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(490, 14327)"
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X.shape"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"array([2, 2, 0, 2, 1, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n",
" 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n",
" 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 1, 2, 0, 2, 2, 2, 1, 2, 2, 2, 2, 2,\n",
" 2, 2, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0,\n",
" 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 1, 0, 0, 2, 2, 2, 2, 2, 2,\n",
" 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 2, 1, 0, 0, 2, 2, 1,\n",
" 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,\n",
" 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 0, 0, 2, 0, 2, 2, 0, 2,\n",
" 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 0, 2, 2,\n",
" 2, 1, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 0,\n",
" 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 0, 2, 0, 2, 0, 2, 2,\n",
" 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 0, 1, 2, 2, 2, 2, 2, 2,\n",
" 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2,\n",
" 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 0, 0, 1, 2, 2, 2, 2, 0, 2, 2, 2, 2,\n",
" 2, 2, 0, 2, 1, 2, 2, 2, 2, 1, 2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2,\n",
" 0, 2, 0, 2, 2, 0, 2, 2, 2, 1, 2, 2, 0, 2, 2, 1, 2, 2, 0, 0, 2, 2, 0,\n",
" 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 0, 0, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0,\n",
" 0, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2,\n",
" 2, 2, 2, 2, 2, 2, 0, 0, 1, 2, 0, 1, 2, 2, 2, 2, 2, 2, 0, 0, 2, 0, 2,\n",
" 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 0, 2, 2, 2, 0, 0, 1, 2, 2, 2,\n",
" 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 0, 2,\n",
" 2, 0, 0, 0, 2, 2, 0], dtype=int32)"
]
},
"execution_count": 50,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"labels_mbkm"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from sklearn.feature_extraction.text import HashingVectorizer"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"class PartialFitPipeline(Pipeline):\n",
" def partial_fit(self, X, y=None):\n",
" Xt = X\n",
" for name, transform in self.steps[:-1]:\n",
" Xt = transform.transform(Xt)\n",
" return self.steps[-1][1].partial_fit(Xt, y=y)"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"pipeline = PartialFitPipeline([('feature_extraction', HashingVectorizer()),\n",
" ('clusterer', MiniBatchKMeans(random_state=14, n_clusters=3))\n",
" ])"
]
},
{
"cell_type": "code",
"execution_count": 75,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"batch_size = 10\n",
"\n",
"for iteration in range(int(len(documents) / batch_size)):\n",
" start = batch_size * iteration\n",
" end = batch_size * (iteration + 1)\n",
" pipeline.partial_fit(documents[start:end])"
]
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"array([0, 2, 2, 0, 1, 0, 2, 2, 2, 2, 1, 2, 2, 0, 2, 2, 0, 2, 0, 2, 2, 1, 2,\n",
" 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2,\n",
" 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 0, 2, 1, 2, 2, 2, 1, 2,\n",
" 2, 2, 2, 1, 1, 1, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 1, 0, 0, 2,\n",
" 1, 2, 2, 2, 1, 0, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 0, 2, 2, 0,\n",
" 0, 2, 0, 2, 2, 0, 0, 2, 2, 2, 1, 0, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1,\n",
" 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 0, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2,\n",
" 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 0, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2,\n",
" 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n",
" 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 2, 2, 2, 0, 0, 0, 1, 0, 2,\n",
" 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 0, 2, 0, 2, 2, 2,\n",
" 0, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 0,\n",
" 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 0, 2, 2, 2, 2,\n",
" 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n",
" 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n",
" 2, 1, 2, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2,\n",
" 0, 2, 2, 1, 0, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2,\n",
" 2, 2, 2, 1, 2, 2, 2, 0, 0, 0, 2, 0, 2, 2, 0, 0, 2, 1, 2, 2, 2, 2, 2,\n",
" 0, 2, 0, 2, 0, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2,\n",
" 0, 2, 0, 2, 2, 2, 2, 1, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2,\n",
" 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n",
" 0, 2, 2, 2, 2, 2, 2], dtype=int32)"
]
},
"execution_count": 76,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"labels = pipeline.predict(documents)\n",
"labels"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.4.0"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
================================================
FILE: Chapter 11/Chapter 11 (CIFAR).ipynb
================================================
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import os\n",
"data_folder = os.path.join(os.path.expanduser(\"~\"), \"Data\", \"cifar-10-batches-py\")\n",
"batch1_filename = os.path.join(data_folder, \"data_batch_1\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import pickle\n",
"# Bigfix thanks to: http://stackoverflow.com/questions/11305790/pickle-incompatability-of-numpy-arrays-between-python-2-and-3\n",
"def unpickle(filename):\n",
" with open(filename, 'rb') as fo:\n",
" return pickle.load(fo, encoding='latin1')"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"batch1 = unpickle(batch1_filename)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"image_index = 100\n",
"image = batch1['data'][image_index]"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"image = image.reshape((32,32, 3), order='F')\n",
"import numpy as np\n",
"image = np.rot90(image, -1)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"%matplotlib inline\n",
"from matplotlib import pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7fe57222a2e8>"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\nTkSuQmCC\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7fe58c2f6278>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.imshow(image)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##Application"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import numpy as np\n",
"batches = []\n",
"for i in range(1, 6):\n",
" batch_filename = os.path.join(data_folder, \"data_batch_{}\".format(i))\n",
" batches.append(unpickle(batch1_filename))\n",
" break #IMPORTANT -- see chapter for explanation of this line"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"X = np.vstack([batch['data'] for batch in batches])"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"X = np.array(X) / X.max()\n",
"X = X.astype(np.float32)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from sklearn.preprocessing import OneHotEncoder\n",
"y = np.hstack(batch['labels'] for batch in batches).flatten()\n",
"y = OneHotEncoder().fit_transform(y.reshape(y.shape[0],1)).todense()\n",
"y = y.astype(np.float32)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from sklearn.cross_validation import train_test_split\n",
"X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) "
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"X_train = X_train.reshape(-1, 3, 32, 32)\n",
"X_test = X_test.reshape(-1, 3, 32, 32)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from lasagne import layers\n",
"layers=[\n",
" ('input', layers.InputLayer),\n",
" ('conv1', layers.Conv2DLayer),\n",
" ('pool1', layers.MaxPool2DLayer),\n",
" ('conv2', layers.Conv2DLayer),\n",
" ('pool2', layers.MaxPool2DLayer),\n",
" ('conv3', layers.Conv2DLayer),\n",
" ('pool3', layers.MaxPool2DLayer),\n",
" ('hidden4', layers.DenseLayer),\n",
" ('hidden5', layers.DenseLayer),\n",
" ('output', layers.DenseLayer),\n",
" ]"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from nolearn.lasagne import NeuralNet\n",
"from lasagne.nonlinearities import sigmoid, softmax\n",
"nnet = NeuralNet(layers=layers,\n",
" input_shape=(None, 3, 32, 32),\n",
" conv1_num_filters=32,\n",
" conv1_filter_size=(3, 3),\n",
" conv2_num_filters=64,\n",
" conv2_filter_size=(2, 2),\n",
" conv3_num_filters=128,\n",
" conv3_filter_size=(2, 2),\n",
" pool1_ds=(2,2),\n",
" pool2_ds=(2,2),\n",
" pool3_ds=(2,2),\n",
" hidden4_num_units=500,\n",
" hidden5_num_units=500,\n",
" output_num_units=10,\n",
" output_nonlinearity=softmax,\n",
" update_learning_rate=0.01,\n",
" update_momentum=0.9,\n",
" regression=True,\n",
" max_epochs=3,\n",
" verbose=1)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" input \t(None, 3, 32, 32) \tproduces 3072 outputs\n",
" conv1 \t(None, 32, 30, 30) \tproduces 28800 outputs\n",
" pool1 \t(None, 32, 15, 15) \tproduces 7200 outputs\n",
" conv2 \t(None, 64, 14, 14) \tproduces 12544 outputs\n",
" pool2 \t(None, 64, 7, 7) \tproduces 3136 outputs\n",
" conv3 \t(None, 128, 6, 6) \tproduces 4608 outputs\n",
" pool3 \t(None, 128, 3, 3) \tproduces 1152 outputs\n",
" hidden4 \t(None, 500) \tproduces 500 outputs\n",
" hidden5 \t(None, 500) \tproduces 500 outputs\n",
" output \t(None, 10) \tproduces 10 outputs\n",
"\n",
" Epoch | Train loss | Valid loss | Train / Val | Valid acc | Dur\n",
"--------|--------------|--------------|---------------|-------------|-------\n",
" 1 | \u001b[94m 0.090018\u001b[0m | \u001b[32m 0.090022\u001b[0m | 0.999963 | | 103.9s\n",
" 2 | \u001b[94m 0.089988\u001b[0m | \u001b[32m 0.090000\u001b[0m | 0.999858 | | 103.8s\n",
" 3 | \u001b[94m 0.089961\u001b[0m | \u001b[32m 0.089982\u001b[0m | 0.999759 | | 104.2s\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/usr/local/lib/python3.4/dist-packages/Lasagne-0.1dev-py3.4.egg/lasagne/init.py:30: UserWarning: The uniform initializer no longer uses Glorot et al.'s approach to determine the bounds, but defaults to the range (-0.01, 0.01) instead. Please use the new GlorotUniform initializer to get the old behavior. GlorotUniform is now the default for all layers.\n",
" warnings.warn(\"The uniform initializer no longer uses Glorot et al.'s \"\n"
]
},
{
"data": {
"text/plain": [
"NeuralNet(X_tensor_type=<function tensor4 at 0x7fe55b73a0d0>,\n",
" batch_iterator_test=<nolearn.lasagne.BatchIterator object at 0x7fe559e70710>,\n",
" batch_iterator_train=<nolearn.lasagne.BatchIterator object at 0x7fe559e706d8>,\n",
" conv1_filter_size=(3, 3), conv1_num_filters=32,\n",
" conv2_filter_size=(2, 2), conv2_num_filters=64,\n",
" conv3_filter_size=(2, 2), conv3_num_filters=128, eval_size=0.2,\n",
" hidden4_num_units=500, hidden5_num_units=500,\n",
" input_shape=(None, 3, 32, 32),\n",
" layers=[('input', <class 'lasagne.layers.input.InputLayer'>), ('conv1', <class 'lasagne.layers.conv.Conv2DLayer'>), ('pool1', <class 'lasagne.layers.pool.MaxPool2DLayer'>), ('conv2', <class 'lasagne.layers.conv.Conv2DLayer'>), ('pool2', <class 'lasagne.layers.pool.MaxPool2DLayer'>), ('conv3', <class..., <class 'lasagne.layers.dense.DenseLayer'>), ('output', <class 'lasagne.layers.dense.DenseLayer'>)],\n",
" loss=None, max_epochs=3, more_params={},\n",
" objective=<class 'lasagne.objectives.Objective'>,\n",
" objective_loss_function=<function mse at 0x7fe559e622f0>,\n",
" on_epoch_finished=(), on_training_finished=(),\n",
" output_nonlinearity=<theano.tensor.nnet.nnet.Softmax object at 0x7fe57cfddba8>,\n",
" output_num_units=10, pool1_ds=(2, 2), pool2_ds=(2, 2),\n",
" pool3_ds=(2, 2), regression=True,\n",
" update=<function nesterov_momentum at 0x7fe559e628c8>,\n",
" update_learning_rate=0.01, update_momentum=0.9,\n",
" use_label_encoder=False, verbose=1,\n",
" y_tensor_type=TensorType(float32, matrix))"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"nnet.fit(X_train, y_train)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.0364246254873\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/usr/local/lib/python3.4/dist-packages/sklearn/metrics/metrics.py:1771: UndefinedMetricWarning: F-score is ill-defined and being set to 0.0 in labels with no predicted samples.\n",
" 'precision', 'predicted', average, warn_for)\n"
]
}
],
"source": [
"from sklearn.metrics import f1_score\n",
"y_pred = nnet.predict(X_test)\n",
"print(f1_score(y_test.argmax(axis=1), y_pred.argmax(axis=1)))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.4.0"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
================================================
FILE: Chapter 11/Chapter 11 (Theano and Lasagne).ipynb
================================================
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##Cifar Dataset"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import os\n",
"data_folder = os.path.join(os.path.expanduser(\"~\"), \"Data\", \"cifar-10-batches-py\")\n",
"batch1_filename = os.path.join(data_folder, \"data_batch_1\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import pickle\n",
"# Bigfix thanks to: http://stackoverflow.com/questions/11305790/pickle-incompatability-of-numpy-arrays-between-python-2-and-3\n",
"def unpickle(filename):\n",
" with open(filename, 'rb') as fo:\n",
" return pickle.load(fo, encoding='latin1')"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"batch1 = unpickle(batch1_filename)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"image_index = 100\n",
"image = batch1['data'][image_index]"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"image = image.reshape((32,32, 3), order='F')\n",
"import numpy as np\n",
"image = np.rot90(image, -1)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"%matplotlib inline\n",
"from matplotlib import pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7f12f47efac8>"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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
gitextract_qbrouktj/ ├── Chapter 1/ │ ├── affinity_dataset.txt │ ├── ch1_affinity.ipynb │ ├── ch1_affinity_create.ipynb │ └── ch1_oner_application.ipynb ├── Chapter 10/ │ └── Chapter 10 Clusterer.ipynb ├── Chapter 11/ │ ├── Chapter 11 (CIFAR).ipynb │ └── Chapter 11 (Theano and Lasagne).ipynb ├── Chapter 12/ │ ├── CH12 MapReduce Basics.ipynb │ ├── Chapter 12 (NB Predict).ipynb │ ├── Chapter 12 (Test load).ipynb │ ├── extract_posts.py │ ├── nb_predict.py │ └── nb_train.py ├── Chapter 2/ │ └── Ionosphere Nearest Neighbour.ipynb ├── Chapter 3/ │ └── Basketball Results.ipynb ├── Chapter 4/ │ └── ch4 Affinity Analysis.ipynb ├── Chapter 5/ │ ├── adult_tests.py │ ├── ch5_adult.ipynb │ └── ch5_advertisements.ipynb ├── Chapter 6/ │ ├── ch6_classify_twitter.ipynb │ ├── ch6_get_twitter.ipynb │ ├── ch6_label_twitter.ipynb │ └── replicable_dataset.json ├── Chapter 7/ │ ├── CH7 From Load.ipynb │ ├── ch7_collect_twitter_data.ipynb │ └── ch7_part2_twitter.ipynb ├── Chapter 8/ │ ├── CH8 Rewrite.ipynb │ └── Sigmoid.ipynb ├── Chapter 9/ │ ├── Chapter 9 Authorship Analysis.ipynb │ └── getdata.py ├── LICENSE └── README.md
SYMBOL INDEX (17 symbols across 4 files)
FILE: Chapter 12/extract_posts.py
class ExtractPosts (line 9) | class ExtractPosts(MRJob):
method mapper (line 14) | def mapper(self, key, line):
FILE: Chapter 12/nb_predict.py
class NaiveBayesTrainer (line 11) | class NaiveBayesTrainer(MRJob):
method steps (line 13) | def steps(self):
method extract_words_mapping (line 20) | def extract_words_mapping(self, key, value):
method reducer_count_words (line 33) | def reducer_count_words(self, key, counts):
method predict_mapper (line 38) | def predict_mapper(self, key, value):
method ratio_mapper (line 45) | def ratio_mapper(self, word, value):
method sorter_reducer (line 52) | def sorter_reducer(self, key, values):
FILE: Chapter 12/nb_train.py
class NaiveBayesTrainer (line 11) | class NaiveBayesTrainer(MRJob):
method steps (line 13) | def steps(self):
method extract_words_mapping (line 20) | def extract_words_mapping(self, key, value):
method reducer_count_words (line 33) | def reducer_count_words(self, key, counts):
method compare_words_reducer (line 38) | def compare_words_reducer(self, word, values):
method ratio_mapper (line 45) | def ratio_mapper(self, word, value):
method sorter_reducer (line 52) | def sorter_reducer(self, key, values):
FILE: Chapter 5/adult_tests.py
function test_meandiscrete (line 4) | def test_meandiscrete():
Condensed preview — 32 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,045K chars).
[
{
"path": "Chapter 1/affinity_dataset.txt",
"chars": 1000,
"preview": "0 0 1 1 1\n1 1 0 1 0\n1 0 1 1 0\n0 0 1 1 1\n0 1 0 0 1\n0 1 0 0 0\n1 0 0 0 1\n1 0 0 0 1\n0 0 0 1 1\n0 0 1 1 1\n1 1 0 0 1\n0 1 0 0 0\n"
},
{
"path": "Chapter 1/ch1_affinity.ipynb",
"chars": 14242,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 1,\n \"metadata\": {\n \"collapsed\": false\n },\n \"out"
},
{
"path": "Chapter 1/ch1_affinity_create.ipynb",
"chars": 3544,
"preview": "{\n \"metadata\": {\n \"name\": \"\"\n },\n \"nbformat\": 3,\n \"nbformat_minor\": 0,\n \"worksheets\": [\n {\n \"cells\": [\n {\n \"c"
},
{
"path": "Chapter 1/ch1_oner_application.ipynb",
"chars": 13797,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 1,\n \"metadata\": {\n \"collapsed\": false\n },\n \"out"
},
{
"path": "Chapter 10/Chapter 10 Clusterer.ipynb",
"chars": 78925,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 1,\n \"metadata\": {\n \"collapsed\": false\n },\n \"out"
},
{
"path": "Chapter 11/Chapter 11 (CIFAR).ipynb",
"chars": 58837,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 1,\n \"metadata\": {\n \"collapsed\": true\n },\n \"outp"
},
{
"path": "Chapter 11/Chapter 11 (Theano and Lasagne).ipynb",
"chars": 62409,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"##Cifar Dataset\"\n ]\n },\n {\n \""
},
{
"path": "Chapter 12/CH12 MapReduce Basics.ipynb",
"chars": 38759,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"##Intuition\"\n ]\n },\n {\n \"cell"
},
{
"path": "Chapter 12/Chapter 12 (NB Predict).ipynb",
"chars": 10578,
"preview": "{\n \"metadata\": {\n \"name\": \"\"\n },\n \"nbformat\": 3,\n \"nbformat_minor\": 0,\n \"worksheets\": [\n {\n \"cells\": [\n {\n \"c"
},
{
"path": "Chapter 12/Chapter 12 (Test load).ipynb",
"chars": 1730,
"preview": "{\n \"metadata\": {\n \"name\": \"\"\n },\n \"nbformat\": 3,\n \"nbformat_minor\": 0,\n \"worksheets\": [\n {\n \"cells\": [\n {\n \"c"
},
{
"path": "Chapter 12/extract_posts.py",
"chars": 882,
"preview": "import os\nimport re\nfrom mrjob.job import MRJob\nfrom mrjob.step import MRStep\n\nword_search_re = re.compile(r\"[\\w']+\")\n\n\n"
},
{
"path": "Chapter 12/nb_predict.py",
"chars": 1986,
"preview": "import os\nimport re\nimport numpy as np\nfrom mrjob.job import MRJob\nfrom mrjob.step import MRStep\nfrom operator import it"
},
{
"path": "Chapter 12/nb_train.py",
"chars": 2021,
"preview": "import os\nimport re\nimport numpy as np\nfrom mrjob.job import MRJob\nfrom mrjob.step import MRStep\nfrom operator import it"
},
{
"path": "Chapter 2/Ionosphere Nearest Neighbour.ipynb",
"chars": 128669,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 6,\n \"metadata\": {\n \"collapsed\": false\n },\n \"out"
},
{
"path": "Chapter 3/Basketball Results.ipynb",
"chars": 77572,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 1,\n \"metadata\": {\n \"collapsed\": false\n },\n \"out"
},
{
"path": "Chapter 4/ch4 Affinity Analysis.ipynb",
"chars": 49404,
"preview": "{\n \"metadata\": {\n \"name\": \"\",\n \"signature\": \"sha256:25d074ec46320302c17c06c6abf5418625ce7b1ae12f86ad84fdd3d25968e23e\"\n"
},
{
"path": "Chapter 5/adult_tests.py",
"chars": 1034,
"preview": "import numpy as np\nfrom numpy.testing import assert_array_equal\n\ndef test_meandiscrete():\n X_test = np.array([[ 0, 2"
},
{
"path": "Chapter 5/ch5_adult.ipynb",
"chars": 14241,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 1,\n \"metadata\": {\n \"collapsed\": false\n },\n \"out"
},
{
"path": "Chapter 5/ch5_advertisements.ipynb",
"chars": 29984,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 1,\n \"metadata\": {\n \"collapsed\": false\n },\n \"out"
},
{
"path": "Chapter 6/ch6_classify_twitter.ipynb",
"chars": 5559,
"preview": "{\n \"metadata\": {\n \"name\": \"\",\n \"signature\": \"sha256:0572f58810bcde678e56e4c78ad5181092637198a0b58fe081990b0b1540ee52\"\n"
},
{
"path": "Chapter 6/ch6_get_twitter.ipynb",
"chars": 18409,
"preview": "{\n \"metadata\": {\n \"name\": \"\",\n \"signature\": \"sha256:cb93d043019583326c0d63bbbdc20c5e315beec9df3c4f2372243ab77d035675\"\n"
},
{
"path": "Chapter 6/ch6_label_twitter.ipynb",
"chars": 7192,
"preview": "{\n \"metadata\": {\n \"name\": \"\",\n \"signature\": \"sha256:bedd2d93552b56f12dfc316010dc889b286a3ae6dad17066f6067cfe5a3cc22c\"\n"
},
{
"path": "Chapter 6/replicable_dataset.json",
"chars": 5000,
"preview": "[[546508356979281920, 1], [546508223466192896, 0], [546508177227796480, 0], [546508108789338112, 1], [546508007865987072"
},
{
"path": "Chapter 7/ch7_collect_twitter_data.ipynb",
"chars": 494445,
"preview": "{\n \"metadata\": {\n \"name\": \"\",\n \"signature\": \"sha256:92626e6b8c220e06f64c1f7e8ed2f882c28441fc05cc1d6bd66a84c37e091595\"\n"
},
{
"path": "Chapter 7/ch7_part2_twitter.ipynb",
"chars": 557252,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 1,\n \"metadata\": {\n \"collapsed\": false\n },\n \"out"
},
{
"path": "Chapter 8/CH8 Rewrite.ipynb",
"chars": 292916,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 6,\n \"metadata\": {\n \"collapsed\": false\n },\n \"out"
},
{
"path": "Chapter 8/Sigmoid.ipynb",
"chars": 82973,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 1,\n \"metadata\": {\n \"collapsed\": true\n },\n \"outp"
},
{
"path": "Chapter 9/Chapter 9 Authorship Analysis.ipynb",
"chars": 897166,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 1,\n \"metadata\": {\n \"collapsed\": true\n },\n \"outp"
},
{
"path": "Chapter 9/getdata.py",
"chars": 3658,
"preview": "# Downloads the books and stores them in the below folder\nimport os\nfrom time import sleep\nimport urllib.request\n\ntitles"
},
{
"path": "LICENSE",
"chars": 1079,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2016 Taabish Khan\n\nPermission is hereby granted, free of charge, to any person obta"
},
{
"path": "README.md",
"chars": 2215,
"preview": "This is the code repository for [Learning Data Mining With Python](https://www.packtpub.com/big-data-and-business-intell"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the PacktPublishing/Learning-Data-Mining-with-Python GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 32 files (14.3 MB), approximately 741.0k tokens, and a symbol index with 17 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.