├── .gitignore ├── .tmux.conf ├── LICENSE ├── README.md ├── dataset ├── PreprocessData.csv └── data.csv ├── images ├── 1.png ├── 2.png ├── 3.png └── 4.png ├── notebooks ├── VisualizePreprocess.ipynb └── training_models.ipynb └── scripts ├── bash ├── git_star_pred_DO_conf cmds └── settingUpDOServer.sh ├── nodejs ├── getting_repos_v2.js ├── githubGraphQLApiCallsDO_V2.js ├── githubGraphQLApiCallsDO_V3.js ├── graphql queries ├── package.json ├── test.js └── test3.js └── python ├── json_to_csv.py └── merge.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | # Custom Files 40 | scripts/nodejs/.env 41 | .idea/ 42 | dist 43 | data/ 44 | scripts/nodejs/node_modules 45 | notebooks/.ipynb_checkpoints/ 46 | notebooks/tpot.ipynb -------------------------------------------------------------------------------- /.tmux.conf: -------------------------------------------------------------------------------- 1 | # force a reload of the config file 2 | unbind r 3 | bind r source-file ~/.tmux.conf 4 | 5 | # behavior 6 | set -g base-index 1 # start window numbering from 1 instead of 0 7 | setw -g automatic-rename on # automatically name windows 8 | set -g set-titles on # auto set the terminal's window title 9 | set -g mouse on # enable mouse 10 | 11 | 12 | # Set the default terminal mode to 256color mode 13 | set -g default-terminal "screen-256color" 14 | 15 | # enable activity alerts 16 | setw -g monitor-activity on 17 | set -g visual-activity on 18 | 19 | # Center the window list 20 | set -g status-justify centre 21 | 22 | 23 | # appearance 24 | set -g default-terminal "screen-256color" # full colors for apps 25 | set -g status-left-length 45 26 | set -g status-left '⣿ #[underscore]#20H#[default]:#[fg=black]#S#[default] ⡇' 27 | set -g status-right ' ⣿ ' 28 | setw -g window-status-format ' #I #W ' # window name formatting 29 | setw -g window-status-current-format ' #I #W ' 30 | set -g status-bg colour3 # dark yellow status bar 31 | setw -g window-status-bg colour240 # dark grey window name bg 32 | setw -g window-status-fg white 33 | setw -g window-status-current-bg red # red bg for active window 34 | setw -g window-status-current-fg white 35 | setw -g window-status-current-attr bold 36 | setw -g window-status-attr bold 37 | set -g set-titles-string '[#I] #W' 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 AlphaMinds 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Github Repo Stars Predictor 2 | 3 | ## Overview 4 | It's a github repo star predictor that tries to predict the stars of 5 | any github repository having greater than 100 stars. It predicts based on 6 | the owner/organization's status and activities (commits, forks, comments, 7 | branches, update rate, etc.) on the repository. Different types of models 8 | (Gradient boost, Deep neural network, etc) have been tested successfully 9 | on the dataset we fetched from github apis. 10 | 11 | ## Dataset 12 | We used the github REST api and GraphQL api to collect data of repositories 13 | having more than 100 stars. The data is available in the dataset directory 14 | We were able to collect the data faster using the Digital Ocean's multiple 15 | servers. So we thanks [Digital Ocean](http://digitalocean.com) for providing 16 | free credits to students to use servers. For the details on dataset features 17 | refer the summary section below. 18 | 19 | ## Tools used 20 | - Python 2.7 21 | - Jupyter Notebook 22 | - NumPy 23 | - Sklearn 24 | - Pandas 25 | - Keras 26 | - Cat Boost 27 | - Matplot Lib 28 | - seaborn 29 | 30 | We also used [Google Colab's](http://colab.research.google.com/) GPU notebooks. 31 | So we thank to Google for starting thier colab project for 32 | providing GPUs 33 | 34 | ## Code details 35 | Below is a brief description for the Code files/folder in repo. 36 | 37 | ### Bash Script 38 | - **settingUpDOServer.sh**
39 | filepath: scripts/bash/settingUpDOServer.sh
40 | This is used for configuring the digital ocean server 41 | 42 | ### NodeJs scripts 43 | - **getting_repos_v2.js**
44 | filepath: scripts/nodejs/getting_repos_v2.js
45 | This script fetches the basic info of repos having more than 100 stars using the Github REST API 46 | 47 | - **githubGraphQLApiCallsDO_V2.js**
48 | filepath: scripts/nodejs/githubGraphQLApiCallsDO_V2.js
49 | This script fetches the complete info of the repositories that were fetched by the above 50 | script and uses the Github GraphQL API. It follows the approach of fetching the data 51 | at the fixed rate defined in env file (eg. 730ms per request) 52 | 53 | - **githubGraphQLApiCallsDO_V3.js**
54 | filepath: scripts/nodejs/githubGraphQLApiCallsDO_V3.js
55 | This script fetches the complete info of the repositories that were fetched by the above 56 | script and uses the Github GraphQL API. It follows the approach of requesting data for 57 | next repo after receiving the response of the already sent request. 58 | 59 | ### Python scripts 60 | - **json_to_csv.py**
61 | filepath: scripts/python/json_to_csv.py
62 | This script converts the json data fetched from Github's GraphQL API in the above script to the 63 | equivalent csv file. 64 | 65 | - **merge.py**
66 | filepath: scripts/python/merge.py
67 | This scripts merges all the data in multiple csv files to a single csv file 68 | 69 | ### Jupyter Notebooks 70 | - **VisualizePreprocess.ipynb**
71 | filepath: notebooks/VisualizePreprocess.ipynb
72 | We have done the feature engineering task in this notebook. It visualises the data and correspondingly 73 | creates new features, modifies existing features and removes redundant features. For details 74 | on features created, check the summary below 75 | 76 | - **training_models.ipynb**
77 | filepath: notebooks/training_models.ipynb
78 | In this notebook, we trained different models with hyper parameter tuning on our dataset and compared their result in the end. 79 | For details on models trained, their prediction scores, etc. check the summary below. 80 | 81 | ## Summary 82 | In this project we have tried to predict the number of stars 83 | of a github repository that have more than 100 stars. For this we have 84 | taken the github repository data from github REST api and GraphQL api. 85 | After generating the dataset we visualized and did some feature engineering 86 | with the dataset and after that , finally we come up to the stage where we 87 | applied various models and predicted the model's scores on training and 88 | test data. 89 | 90 | ### Feature Engineering 91 | There are total of 49 features before pre-processing. After pre-processing (adding new features, removal of redundant features and 92 | modifying existing features) the count changes to 54. All the features are listed below. 93 | Some features after pre-processing may not be clear. Please refer to the VisualizePreprocess.ipynb notebook for details. 94 | 95 | 96 | #### Original Features 97 | column 1 | column 2 | column 3 98 | ------------ | ------------- | ------------- 99 | branches | commits | createdAt 100 | description | diskUsage | followers 101 | following | forkCount | gistComments 102 | gistStar | gists | hasWikiEnabled 103 | iClosedComments | iClosedParticipants | iOpenComments 104 | iOpenParticipants | isArchived | issuesClosed 105 | issuesOpen | license | location 106 | login | members | organizations 107 | prClosed | prClosedComments | prClosedCommits 108 | prMerged | prMergedComments | prMergedCommits 109 | prOpen | prOpenComments | prOpenCommits 110 | primaryLanguage | pushedAt | readmeCharCount 111 | readmeLinkCount | readmeSize | readmeWordCount 112 | releases | reponame | repositories 113 | siteAdmin | stars | subscribersCount 114 | tags | type | updatedAt 115 | websiteUrl | 116 | 117 | #### Features after pre-processing 118 | column 1 | column 2 | column 3 119 | ------------ | ------------- | ------------- 120 | branches | commits | createdAt 121 | diskUsage | followers | following 122 | forkCount | gistComments | gistStar 123 | gists | hasWikiEnabled | iClosedComments 124 | iClosedParticipants | iOpenComments | iOpenParticipants 125 | issuesClosed | issuesOpen | members 126 | organizations | prClosed | prClosedComments 127 | prClosedCommits | prMerged | prMergedComments 128 | prMergedCommits | prOpen | prOpenComments 129 | prOpenCommits | pushedAt | readmeCharCount 130 | readmeLinkCount | readmeSize | readmeWordCount 131 | releases | repositories | subscribersCount 132 | tags | type | updatedAt 133 | websiteUrl | desWordCount | desCharCount 134 | mit_license | nan_license | apache_license 135 | other_license | remain_license | JavaScript 136 | Python | Java | Objective 137 | Ruby | PHP | other_language 138 | 139 | 140 | ### Models Trained 141 | - **Gradient Boost Regressor** 142 | - **Cat Boost Regressor** 143 | - **Random Forest Regressor** 144 | - **Deep Neural Network** 145 | 146 | ### Evaluation Metrics 147 | - **R^2 score**
148 | ![R^2 score formula](./images/1.png) 149 | 150 | ### Results 151 | ![Result bar graph of different models](./images/2.png) 152 | -------------------------------------------------------------------------------- /images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/dc8c16a0516fe85ec130caadde5c577493860cb6/images/1.png -------------------------------------------------------------------------------- /images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/dc8c16a0516fe85ec130caadde5c577493860cb6/images/2.png -------------------------------------------------------------------------------- /images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/dc8c16a0516fe85ec130caadde5c577493860cb6/images/3.png -------------------------------------------------------------------------------- /images/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/dc8c16a0516fe85ec130caadde5c577493860cb6/images/4.png -------------------------------------------------------------------------------- /notebooks/training_models.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 6, 6 | "metadata": { 7 | "colab": { 8 | "autoexec": { 9 | "startup": false, 10 | "wait_interval": 0 11 | }, 12 | "base_uri": "https://localhost:8080/", 13 | "height": 312, 14 | "output_extras": [ 15 | { 16 | "item_id": 3 17 | } 18 | ] 19 | }, 20 | "colab_type": "code", 21 | "executionInfo": { 22 | "elapsed": 2079, 23 | "status": "ok", 24 | "timestamp": 1519120778768, 25 | "user": { 26 | "displayName": "Pawan Bansal", 27 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg", 28 | "userId": "102337886470920224775" 29 | }, 30 | "user_tz": -330 31 | }, 32 | "id": "mKFskImGo9qc", 33 | "outputId": "d5204a20-3b54-4176-a625-fbcb8302e98d" 34 | }, 35 | "outputs": [ 36 | { 37 | "name": "stdout", 38 | "output_type": "stream", 39 | "text": [ 40 | "--2018-02-20 09:59:37-- http://=/\n", 41 | "Resolving = (=)... failed: Name or service not known.\n", 42 | "wget: unable to resolve host address ‘=’\n", 43 | "--2018-02-20 09:59:37-- https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/master/PreprocessData.csv\n", 44 | "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.0.133, 151.101.64.133, 151.101.128.133, ...\n", 45 | "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.0.133|:443... connected.\n", 46 | "HTTP request sent, awaiting response... 200 OK\n", 47 | "Length: 18616347 (18M) [text/plain]\n", 48 | "Saving to: ‘PreprocessData.csv’\n", 49 | "\n", 50 | "PreprocessData.csv 100%[===================>] 17.75M 38.4MB/s in 0.5s \n", 51 | "\n", 52 | "2018-02-20 09:59:38 (38.4 MB/s) - ‘PreprocessData.csv’ saved [18616347/18616347]\n", 53 | "\n", 54 | "FINISHED --2018-02-20 09:59:38--\n", 55 | "Total wall clock time: 0.9s\n", 56 | "Downloaded: 1 files, 18M in 0.5s (38.4 MB/s)\n" 57 | ] 58 | } 59 | ], 60 | "source": [ 61 | "!wget = 'https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/master/PreprocessData.csv'" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 7, 67 | "metadata": { 68 | "colab": { 69 | "autoexec": { 70 | "startup": false, 71 | "wait_interval": 0 72 | }, 73 | "base_uri": "https://localhost:8080/", 74 | "height": 69, 75 | "output_extras": [ 76 | { 77 | "item_id": 1 78 | } 79 | ] 80 | }, 81 | "colab_type": "code", 82 | "executionInfo": { 83 | "elapsed": 981, 84 | "status": "ok", 85 | "timestamp": 1519120781777, 86 | "user": { 87 | "displayName": "Pawan Bansal", 88 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg", 89 | "userId": "102337886470920224775" 90 | }, 91 | "user_tz": -330 92 | }, 93 | "id": "CJaU70pspQCu", 94 | "outputId": "affdb0a4-3b24-4ba6-83ef-bf17f20739ed" 95 | }, 96 | "outputs": [ 97 | { 98 | "name": "stdout", 99 | "output_type": "stream", 100 | "text": [ 101 | "total 18M\r\n", 102 | "drwxr-xr-x 1 root root 4.0K Feb 20 09:22 datalab\r\n", 103 | "-rw-r--r-- 1 root root 18M Feb 20 09:59 PreprocessData.csv\r\n" 104 | ] 105 | } 106 | ], 107 | "source": [ 108 | "!ls -lh" 109 | ] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "metadata": { 114 | "colab_type": "text", 115 | "id": "yGS-YGdiqIEq" 116 | }, 117 | "source": [ 118 | "# Importing required modules" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": 0, 124 | "metadata": { 125 | "colab": { 126 | "autoexec": { 127 | "startup": false, 128 | "wait_interval": 0 129 | } 130 | }, 131 | "colab_type": "code", 132 | "collapsed": true, 133 | "id": "umNFuu0-xEGK" 134 | }, 135 | "outputs": [], 136 | "source": [ 137 | "!pip install catboost ipywidgets\n", 138 | "!pip install xgboost\n", 139 | "!pip install keras" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 2, 145 | "metadata": { 146 | "colab": { 147 | "autoexec": { 148 | "startup": false, 149 | "wait_interval": 0 150 | } 151 | }, 152 | "colab_type": "code", 153 | "id": "MkaUKVnepe07" 154 | }, 155 | "outputs": [ 156 | { 157 | "name": "stderr", 158 | "output_type": "stream", 159 | "text": [ 160 | "Using Theano backend.\n" 161 | ] 162 | }, 163 | { 164 | "ename": "ImportError", 165 | "evalue": "No module named theano", 166 | "output_type": "error", 167 | "traceback": [ 168 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 169 | "\u001b[0;31mImportError\u001b[0m Traceback (most recent call last)", 170 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0msklearn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mensemble\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mRandomForestRegressor\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 29\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmodels\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mSequential\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 30\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlayers\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mDense\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mDropout\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mBatchNormalization\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 31\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwrappers\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mscikit_learn\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mKerasRegressor\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 171 | "\u001b[0;32m/home/pawan/anaconda3/envs/env2.7/lib/python2.7/site-packages/keras/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0m__future__\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mabsolute_import\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mutils\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mactivations\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mapplications\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 172 | "\u001b[0;32m/home/pawan/anaconda3/envs/env2.7/lib/python2.7/site-packages/keras/utils/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mdata_utils\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mio_utils\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mconv_utils\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 7\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;31m# Globally-importable utils.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 173 | "\u001b[0;32m/home/pawan/anaconda3/envs/env2.7/lib/python2.7/site-packages/keras/utils/conv_utils.py\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0msix\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmoves\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mnumpy\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 9\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mbackend\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mK\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", 174 | "\u001b[0;32m/home/pawan/anaconda3/envs/env2.7/lib/python2.7/site-packages/keras/backend/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 79\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0m_BACKEND\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'theano'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 80\u001b[0m \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstderr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwrite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Using Theano backend.\\n'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 81\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mtheano_backend\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 82\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0m_BACKEND\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'tensorflow'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 83\u001b[0m \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstderr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwrite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Using TensorFlow backend.\\n'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 175 | "\u001b[0;32m/home/pawan/anaconda3/envs/env2.7/lib/python2.7/site-packages/keras/backend/theano_backend.py\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mcollections\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mdefaultdict\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mcontextlib\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mcontextmanager\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mtheano\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 8\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mtheano\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mtensor\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mT\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mtheano\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msandbox\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrng_mrg\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mMRG_RandomStreams\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mRandomStreams\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 176 | "\u001b[0;31mImportError\u001b[0m: No module named theano" 177 | ] 178 | } 179 | ], 180 | "source": [ 181 | "# Handle table-like data and matrices\n", 182 | "import numpy as np\n", 183 | "import pandas as pd\n", 184 | "\n", 185 | "# Visualisation\n", 186 | "import matplotlib as mpl\n", 187 | "import matplotlib.pyplot as plt\n", 188 | "import matplotlib.pylab as pylab\n", 189 | "import seaborn as sns\n", 190 | "\n", 191 | "# Configure visualisations\n", 192 | "%matplotlib inline\n", 193 | "color = sns.color_palette()\n", 194 | "pd.options.mode.chained_assignment = None\n", 195 | "pd.options.display.max_columns = 999\n", 196 | "# mpl.style.use( 'ggplot' )\n", 197 | "sns.set_style( 'whitegrid' )\n", 198 | "pylab.rcParams[ 'figure.figsize' ] = 10,8\n", 199 | "seed = 7\n", 200 | "\n", 201 | "# importing libraries\n", 202 | "from sklearn.preprocessing import StandardScaler\n", 203 | "from sklearn.model_selection import train_test_split\n", 204 | "from sklearn.metrics import r2_score, mean_squared_error\n", 205 | "from sklearn.ensemble import GradientBoostingRegressor\n", 206 | "from catboost import CatBoostRegressor\n", 207 | "from sklearn.ensemble import RandomForestRegressor\n", 208 | "\n", 209 | "from keras.models import Sequential\n", 210 | "from keras.layers import Dense, Dropout, BatchNormalization\n", 211 | "from keras.wrappers.scikit_learn import KerasRegressor\n", 212 | "from sklearn.model_selection import cross_val_score, KFold\n", 213 | "from sklearn.pipeline import Pipeline\n", 214 | "\n", 215 | "np.random.seed(seed)" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": 5, 221 | "metadata": { 222 | "colab": { 223 | "autoexec": { 224 | "startup": false, 225 | "wait_interval": 0 226 | } 227 | }, 228 | "colab_type": "code", 229 | "collapsed": true, 230 | "id": "IJ4mvGdrpmTN" 231 | }, 232 | "outputs": [], 233 | "source": [ 234 | "data = pd.read_csv('../dataset/PreprocessData.csv').iloc[:, 1:]" 235 | ] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "execution_count": 6, 240 | "metadata": { 241 | "colab": { 242 | "autoexec": { 243 | "startup": false, 244 | "wait_interval": 0 245 | } 246 | }, 247 | "colab_type": "code", 248 | "collapsed": true, 249 | "id": "YHMzBJLtp73R" 250 | }, 251 | "outputs": [], 252 | "source": [ 253 | "X = data.drop(['stars'] , axis =1)\n", 254 | "y = data.stars" 255 | ] 256 | }, 257 | { 258 | "cell_type": "markdown", 259 | "metadata": { 260 | "colab_type": "text", 261 | "id": "BYAwV5zRqDfT" 262 | }, 263 | "source": [ 264 | "# Feature normalization" 265 | ] 266 | }, 267 | { 268 | "cell_type": "code", 269 | "execution_count": 0, 270 | "metadata": { 271 | "colab": { 272 | "autoexec": { 273 | "startup": false, 274 | "wait_interval": 0 275 | } 276 | }, 277 | "colab_type": "code", 278 | "collapsed": true, 279 | "id": "UsGtaizwp_Sq" 280 | }, 281 | "outputs": [], 282 | "source": [ 283 | "s = StandardScaler()\n", 284 | "X = s.fit_transform(X)" 285 | ] 286 | }, 287 | { 288 | "cell_type": "code", 289 | "execution_count": 107, 290 | "metadata": { 291 | "colab": { 292 | "autoexec": { 293 | "startup": false, 294 | "wait_interval": 0 295 | }, 296 | "base_uri": "https://localhost:8080/", 297 | "height": 243, 298 | "output_extras": [ 299 | { 300 | "item_id": 1 301 | } 302 | ] 303 | }, 304 | "colab_type": "code", 305 | "executionInfo": { 306 | "elapsed": 803, 307 | "status": "ok", 308 | "timestamp": 1519125771476, 309 | "user": { 310 | "displayName": "Pawan Bansal", 311 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg", 312 | "userId": "102337886470920224775" 313 | }, 314 | "user_tz": -330 315 | }, 316 | "id": "ipEcS8nmqC4v", 317 | "outputId": "6e653f89-1d99-4465-eca3-67442598c20a" 318 | }, 319 | "outputs": [ 320 | { 321 | "data": { 322 | "text/plain": [ 323 | "array([[-0.09745647, 0.00614558, 0.23250482, ..., -0.23044367,\n", 324 | " -0.22388323, -0.84232977],\n", 325 | " [-0.09745647, -0.08776201, 0.23293463, ..., -0.23044367,\n", 326 | " -0.22388323, -0.84232977],\n", 327 | " [-0.09745647, -0.09548965, 0.23228991, ..., -0.23044367,\n", 328 | " -0.22388323, 1.1871835 ],\n", 329 | " ...,\n", 330 | " [ 0.00197165, -0.0922978 , 0.23218246, ..., -0.23044367,\n", 331 | " -0.22388323, 1.1871835 ],\n", 332 | " [-0.07259944, -0.11128091, 0.23223618, ..., -0.23044367,\n", 333 | " -0.22388323, 1.1871835 ],\n", 334 | " [-0.09745647, -0.10741709, 0.23304208, ..., -0.23044367,\n", 335 | " -0.22388323, 1.1871835 ]])" 336 | ] 337 | }, 338 | "execution_count": 107, 339 | "metadata": { 340 | "tags": [] 341 | }, 342 | "output_type": "execute_result" 343 | } 344 | ], 345 | "source": [ 346 | "X" 347 | ] 348 | }, 349 | { 350 | "cell_type": "markdown", 351 | "metadata": { 352 | "colab_type": "text", 353 | "id": "OYVDATBlqNOq" 354 | }, 355 | "source": [ 356 | "# train test data splitting" 357 | ] 358 | }, 359 | { 360 | "cell_type": "code", 361 | "execution_count": 0, 362 | "metadata": { 363 | "colab": { 364 | "autoexec": { 365 | "startup": false, 366 | "wait_interval": 0 367 | } 368 | }, 369 | "colab_type": "code", 370 | "collapsed": true, 371 | "id": "Hg2sfmChqLFZ" 372 | }, 373 | "outputs": [], 374 | "source": [ 375 | "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.10, random_state=42)" 376 | ] 377 | }, 378 | { 379 | "cell_type": "code", 380 | "execution_count": 0, 381 | "metadata": { 382 | "colab": { 383 | "autoexec": { 384 | "startup": false, 385 | "wait_interval": 0 386 | } 387 | }, 388 | "colab_type": "code", 389 | "collapsed": true, 390 | "id": "pS1m7NZgqO28" 391 | }, 392 | "outputs": [], 393 | "source": [ 394 | "training_scores = []\n", 395 | "test_scores = []\n", 396 | "models = []" 397 | ] 398 | }, 399 | { 400 | "cell_type": "markdown", 401 | "metadata": { 402 | "colab_type": "text", 403 | "id": "F0DCAR2DqSRD" 404 | }, 405 | "source": [ 406 | "\n", 407 | "# Training Models" 408 | ] 409 | }, 410 | { 411 | "cell_type": "markdown", 412 | "metadata": { 413 | "colab_type": "text", 414 | "id": "mZTYSuGZqWkt" 415 | }, 416 | "source": [ 417 | "## 1. Gradient Boost" 418 | ] 419 | }, 420 | { 421 | "cell_type": "code", 422 | "execution_count": 0, 423 | "metadata": { 424 | "colab": { 425 | "autoexec": { 426 | "startup": false, 427 | "wait_interval": 0 428 | } 429 | }, 430 | "colab_type": "code", 431 | "collapsed": true, 432 | "id": "n6P0p8WyqQML" 433 | }, 434 | "outputs": [], 435 | "source": [ 436 | "models.append(\"gradient boost\")" 437 | ] 438 | }, 439 | { 440 | "cell_type": "code", 441 | "execution_count": 18, 442 | "metadata": { 443 | "colab": { 444 | "autoexec": { 445 | "startup": false, 446 | "wait_interval": 0 447 | }, 448 | "base_uri": "https://localhost:8080/", 449 | "height": 469, 450 | "output_extras": [ 451 | { 452 | "item_id": 22 453 | } 454 | ] 455 | }, 456 | "colab_type": "code", 457 | "executionInfo": { 458 | "elapsed": 145023, 459 | "status": "ok", 460 | "timestamp": 1519121157763, 461 | "user": { 462 | "displayName": "Pawan Bansal", 463 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg", 464 | "userId": "102337886470920224775" 465 | }, 466 | "user_tz": -330 467 | }, 468 | "id": "_mcw-FEgqcYC", 469 | "outputId": "b5b57af3-c9c1-4e87-8987-b6fe4d2f543d" 470 | }, 471 | "outputs": [ 472 | { 473 | "name": "stdout", 474 | "output_type": "stream", 475 | "text": [ 476 | " Iter Train Loss Remaining Time \n", 477 | " 1 2314275.3681 2.45m\n", 478 | " 2 2034234.0235 2.41m\n", 479 | " 3 1803572.2337 2.37m\n", 480 | " 4 1608749.3223 2.34m\n", 481 | " 5 1445890.2822 2.33m\n", 482 | " 6 1307594.0384 2.31m\n", 483 | " 7 1188230.8595 2.30m\n", 484 | " 8 1093410.7788 2.31m\n", 485 | " 9 1009625.5156 2.30m\n", 486 | " 10 942921.5465 2.30m\n", 487 | " 20 596844.4649 2.25m\n", 488 | " 30 497781.8140 2.22m\n", 489 | " 40 452724.3501 2.20m\n", 490 | " 50 423902.1842 2.17m\n", 491 | " 60 400324.1880 2.14m\n", 492 | " 70 384742.5304 2.11m\n", 493 | " 80 371501.3233 2.07m\n", 494 | " 90 360896.1303 2.02m\n", 495 | " 100 351778.4518 1.97m\n", 496 | " 200 292815.3392 1.45m\n", 497 | " 300 262845.3144 57.60s\n", 498 | " 400 241005.6847 28.64s\n", 499 | " 500 224750.7518 0.00s\n", 500 | "('training set performance: ', 0.9152585634503211)\n", 501 | "('training set performance: ', 0.7994006303226393)\n" 502 | ] 503 | } 504 | ], 505 | "source": [ 506 | "reg = GradientBoostingRegressor(verbose = 1, n_estimators = 500)\n", 507 | "reg.fit(X_train , y_train)\n", 508 | "\n", 509 | "training_score = reg.score(X_train, y_train)\n", 510 | "test_score = reg.score(X_test, y_test)\n", 511 | "\n", 512 | "training_scores.append(training_score)\n", 513 | "test_scores.append(test_score)\n", 514 | "print(\"training set performance: \", training_score)\n", 515 | "print(\"test set performance: \", test_score)" 516 | ] 517 | }, 518 | { 519 | "cell_type": "code", 520 | "execution_count": 34, 521 | "metadata": { 522 | "colab": { 523 | "autoexec": { 524 | "startup": false, 525 | "wait_interval": 0 526 | }, 527 | "base_uri": "https://localhost:8080/", 528 | "height": 390, 529 | "output_extras": [ 530 | { 531 | "item_id": 1 532 | } 533 | ] 534 | }, 535 | "colab_type": "code", 536 | "executionInfo": { 537 | "elapsed": 1096, 538 | "status": "ok", 539 | "timestamp": 1519121952990, 540 | "user": { 541 | "displayName": "Pawan Bansal", 542 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg", 543 | "userId": "102337886470920224775" 544 | }, 545 | "user_tz": -330 546 | }, 547 | "id": "LpUOOyN9qxZ3", 548 | "outputId": "3fd57b7e-60f6-4f4e-d4bc-f8d72ea1a2d5" 549 | }, 550 | "outputs": [ 551 | { 552 | "data": { 553 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAf8AAAF1CAYAAADm2uMAAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4yLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvNQv5yAAAIABJREFUeJzt3Wt8VNW9PvBnrpnJZXIfCBTFgEJK\nQixEgdAoiECMgrEKCmJrxSvYSqXaGBGhrYLY9KAWD4pFKYpwjP1Q8CBQrgckRJNUJPlDES0tQiCZ\nkGRIMpO5ZP9fxBlymcueZO7zfF/Bnp09a6+Z2b+91l7rtySCIAggIiKiiCENdAGIiIjIvxj8iYiI\nIgyDPxERUYRh8CciIoowDP5EREQRhsGfiIgowsgDXQB/qaysDHQRiIiI/G7s2LG9tkVM8AccV0Bf\nVVZWevV4JB7rPnBY94HF+g+cUK17Zw1fdvsTERFFGAZ/IiKiCMPgT0REFGEY/ImIiCIMgz8REVGE\nYfAnIiKKMAz+REREEYbBn4iIKMIw+BMFOaPJglpdK4wmS6CLQkRhIqIy/BGFEqu1A+u31+BodS3q\nmwxITVBjfGYaHpoxCjIZ79uJqO8Y/ImC1PrtNdh26Fv7/+saDfb/P1KYFahiEVEYYPOBKAgZTRYc\nra51+NrR6lo+AiCifmHwJwpCjfp21DcZHL6mazKgUd/u5xIRkS/5e2wPu/2JglCiJgqpCWrUNfa+\nAUhJUCNRExWAUhGRtwVqbA9b/kRBSKWUY3xmmsPXxmemQaXkfTtROLCN7alrNEAQroztWb+9xqfv\ny+BPFKQemjEKM/PSoU1UQyoBtIlqzMxLx0MzRgW6aETkBYEc28PmA1GQksmkeKQwCw8UZKBR345E\nTRRb/ERhRMzYnrQU3/zm2fInCnIqpRxpKTEM/ERhxja2xxFfj+1h8CciIgqAQI7tYVOCiIgoQGxj\neI5W10LXZEBKl9H+vsTgT0REFCCBGtvD4E9ERBRgnWN7/BeS+cyfiIgowjD4ExERRRgGfyIiogjD\n4E9ERBRhGPyJiIgijM+HFhoMBhQVFaGhoQHt7e1YsGABRo4ciWeffRZWqxWpqal49dVXoVQqsW3b\nNmzYsAFSqRSzZ8/GrFmzYDabUVRUhPPnz0Mmk2HFihUYMmQITp48iWXLlgEARowYgeXLl/v6VIiI\niMKCz1v++/fvR2ZmJt5//32sXr0aK1euxOuvv465c+di06ZNuPrqq1FaWoq2tjasWbMG7733HjZu\n3IgNGzagqakJn3zyCTQaDT788EM8/vjjKCkpAQC89NJLKC4uxubNm9HS0oKDBw/6+lSIiIjCgs+D\nf0FBAR555BEAQG1tLQYMGIDy8nJMmTIFADB58mSUlZXh2LFjyMrKQlxcHFQqFcaMGYOqqiqUlZVh\n6tSpAIDc3FxUVVXBZDLh3LlzGD16dLdjEBERkXt+yyhw33334cKFC1i7di1+/vOfQ6lUAgCSk5NR\nX18PnU6HpKQk+/5JSUm9tkulUkgkEuh0Omg0Gvu+tmMQERGRe34L/ps3b8aJEyfwzDPPQBAE+/au\n/+7Kk+3O9u2psrJS1H5ieft4JB7rPnBY94HF+g+ccKp7nwf/6upqJCcnIy0tDRkZGbBarYiJiYHR\naIRKpcLFixeh1Wqh1Wqh0+nsf1dXV4frr78eWq0W9fX1GDlyJMxmMwRBQGpqKpqamuz72o7hztix\nY712XpWVlV49HonHug8c1n1gsf4DJ1Tr3tkNi8+f+VdUVGD9+vUAAJ1Oh7a2NuTm5mLXrl0AgN27\ndyMvLw/Z2dk4fvw49Ho9WltbUVVVhZycHEycOBE7d+4E0Dl4cNy4cVAoFEhPT0dFRUW3YxAREZF7\nPm/533fffXj++ecxd+5cGI1GLF26FJmZmfjNb36DLVu2YNCgQSgsLIRCocDixYsxf/58SCQSLFy4\nEHFxcSgoKMCRI0cwZ84cKJVKrFy5EgBQXFyMpUuXoqOjA9nZ2cjNzfX1qRAREYUFnwd/lUpln57X\n1bvvvttrW35+PvLz87tts83t72n48OHYtGmT9wpKREQUIZjhj4iIKMIw+BMREUUYBn8iIqIIw+BP\nREQUYRj8iYiIIgyDPxERUYRh8CciIoowDP5EREQRhsGfiIgowjD4ExERRRgGfyIiogjD4E9ERBRh\nGPyJiIgiDIM/EZGHjCYLanWtMJosgS4KUZ/4fElfIqJwYbV2YP32GhytrkV9kwGpCWqMz0zDQzNG\nQSZjW4pCB4M/EZFI67fXYNuhb+3/r2s02P//SGFWoIpF5DHeqhIRiWA0WXC0utbha0era/kIgEIK\ngz8RkQiN+nbUNxkcvqZrMqBR3+7nEhH1HYM/EZEIiZoopCaoHb6WkqBGoibKzyUi6jsGfyIiEVRK\nOcZnpjl8bXxmGlRKDqGi0MFvKxGRSA/NGAWg8xm/rsmAlC6j/YlCCYM/EZFIMpkUjxRm4YGCDDTq\n25GoiWKLn0ISv7VERB5SKeVIS+Hlk0IXn/kTERFFGAZ/IiKiCMPgT0REFGEY/ImIiCIMgz8REVGE\nYfAnCgJcIpYChd+9yMS5KkQBxCViKVD43YtsDP5EAcQlYilQ+N2LbLy9IwoQLhEbOJHe1c3vHrHl\nTxQgYpaIZRY572JXdyd+9yhyvu1EQYZLxPqfrau7rtEAQbjS1b1+e02gi+ZX/O4Rgz9RgHCJWP9i\nV/cV/O4RP2GiAOISsf7Dru7u+N2LbJHzTScKQlwi1n9sXd11jb1vACKxq5vfvcjml0961apVqKys\nhMViwWOPPYZ9+/ahpqYGCQkJAID58+dj0qRJ2LZtGzZs2ACpVIrZs2dj1qxZMJvNKCoqwvnz5yGT\nybBixQoMGTIEJ0+exLJlywAAI0aMwPLly/1xKkQ+wSVifc/W1d11eptNJHd187sXmXz+iR89ehRf\nf/01tmzZgsbGRtx1110YP348nn76aUyePNm+X1tbG9asWYPS0lIoFArcc889mDp1Kvbv3w+NRoOS\nkhIcPnwYJSUlWL16NV566SUUFxdj9OjRWLx4MQ4ePIibb77Z16dDRCGMXd1EnXwe/G+44QaMHj0a\nAKDRaGAwGGC1Wnvtd+zYMWRlZSEuLg4AMGbMGFRVVaGsrAyFhYUAgNzcXBQXF8NkMuHcuXP2406e\nPBllZWUM/kTkEru6iTr5fLS/TCZDdHQ0AKC0tBQ33XQTZDIZ3n//ffz0pz/Fr371K1y6dAk6nQ5J\nSUn2v0tKSkJ9fX237VKpFBKJBDqdDhqNxr5vcnIy6uvrfX0qRBQmOru6Yxj4KWL57Zu/Z88elJaW\nYv369aiurkZCQgIyMjLw9ttv409/+hN+9KMfddtfEASHx3G03dm+PVVWVnpecD8ej8Rj3QcO6z6w\nWP+BE05175fgf+jQIaxduxbvvPMO4uLiMGHCBPtrt9xyC5YtW4bp06dDp9PZt9fV1eH666+HVqtF\nfX09Ro4cCbPZDEEQkJqaiqamJvu+Fy9ehFardVuOsWPHeu2cKisrvXo8Eo91Hzis+8Bi/QdOqNa9\nsxsWn3f7X758GatWrcJbb71lH93/i1/8AmfPngUAlJeX49prr0V2djaOHz8OvV6P1tZWVFVVIScn\nBxMnTsTOnTsBAPv378e4ceOgUCiQnp6OiooKAMDu3buRl5fn61MhIiIKCz5v+e/YsQONjY1YtGiR\nfdtPfvITLFq0CGq1GtHR0VixYgVUKhUWL16M+fPnQyKRYOHChYiLi0NBQQGOHDmCOXPmQKlUYuXK\nlQCA4uJiLF26FB0dHcjOzkZubq6vT4WIiCgs+Dz433vvvbj33nt7bb/rrrt6bcvPz0d+fn63bba5\n/T0NHz4cmzZt8l5BiYiIIgRz+xMREUUYBn8iIqIIw+BPREQUYRj8iYiIIgyDPxERUYRh8CciIoow\nDP5EREQRhsGfiIgowjD4ExERRRgGfyIiogjD4E9ERBRhGPyJiIgiDIM/ERFRhGHwJyIiijAM/kRE\nRBGGwZ+IiJwymiyo1bXCaLIEuijkRfJAF4CIiIKP1dqB9dtrcLS6FvVNBqQmqDE+Mw0PzRgFmYzt\nxlDH4E9ERL2s316DbYe+tf+/rtFg//8jhVmBKhZ5CW/fiIioG6PJgqPVtQ5fO1pdy0cAYYDBn4iI\numnUt6O+yeDwNV2TAY36dj+XiLyNwZ9CHgckEXlXoiYKqQlqh6+lJKiRqInyc4nI2/jMn0IWByQR\n+YZKKcf4zLRuz/xtxmemQaVk6Ah1/AQpZHFAEpHvPDRjFIDOZ/y6JgNSutxcU+hj8KeQ5G5A0gMF\nGWydEPWDTCbFI4VZeKAgA436diRqovibCiPsG6WQxAFJRP6hUsqRlhLDwB9mGPwpJHFAEhFR3zH4\nU0iyDUhyhAOSiIhc4xWSQhYHJBER9Q2DP4UsDkgiIuobXikp5HUOSOJXmYhILD7zJyJygtkjKVyx\nuURE1AOzR1K4Y/AnIuqB2SMp3PEWloioCy5nS5GAwZ+IqAtmj6RIwOBPRNQFs0dSJGDwJyLqgtkj\nKRLwW0xE1AOzR1K480vwX7VqFSorK2GxWPDYY48hKysLzz77LKxWK1JTU/Hqq69CqVRi27Zt2LBh\nA6RSKWbPno1Zs2bBbDajqKgI58+fh0wmw4oVKzBkyBCcPHkSy5YtAwCMGDECy5cv98epEFEEYPZI\nCnc+7/Y/evQovv76a2zZsgXvvPMOXn75Zbz++uuYO3cuNm3ahKuvvhqlpaVoa2vDmjVr8N5772Hj\nxo3YsGEDmpqa8Mknn0Cj0eDDDz/E448/jpKSEgDASy+9hOLiYmzevBktLS04ePCgr0+FiCIMl7Ol\ncOXz4H/DDTfgtddeAwBoNBoYDAaUl5djypQpAIDJkyejrKwMx44dQ1ZWFuLi4qBSqTBmzBhUVVWh\nrKwMU6dOBQDk5uaiqqoKJpMJ586dw+jRo7sdg4ioK2boI3LM57ezMpkM0dHRAIDS0lLcdNNNOHz4\nMJRKJQAgOTkZ9fX10Ol0SEpKsv9dUlJSr+1SqRQSiQQ6nQ4ajca+r+0Y7lRWVnrz1Lx+PBKPdR84\noVD31g4Bu6uacfKcAc2tVsTHyDBysBrTxsRDJpUEunj9Egr1H67Cqe791pe1Z88elJaWYv369Zg2\nbZp9uyAIDvf3ZLuzfXsaO3asqP3EqKys9OrxSDzWfeCESt2v23oc5ada7P9vbrWi/FQLBgzQhnSG\nvlCp/3AUqnXv7IbFL1P9Dh06hLVr12LdunWIi4tDdHQ0jEYjAODixYvQarXQarXQ6XT2v6mrq7Nv\nt7XqzWYzBEFAamoqmpqa7PvajkFExAx9RO75PPhfvnwZq1atwltvvYWEhAQAnc/ud+3aBQDYvXs3\n8vLykJ2djePHj0Ov16O1tRVVVVXIycnBxIkTsXPnTgDA/v37MW7cOCgUCqSnp6OioqLbMYiImKGP\nyD2fd/vv2LEDjY2NWLRokX3bypUrsWTJEmzZsgWDBg1CYWEhFAoFFi9ejPnz50MikWDhwoWIi4tD\nQUEBjhw5gjlz5kCpVGLlypUAgOLiYixduhQdHR3Izs5Gbm6ur0+FiEKALUNfXWPvGwBm6CPq5PPg\nf++99+Lee+/ttf3dd9/ttS0/Px/5+fndttnm9vc0fPhwbNq0yXsFJaKwYMvQ13VVPhtm6CPqxF8B\nEYUdZugjco3Bn4jCDjP0EbnGXwMRha3ODH28zBH1xFX9iIiIIgyDPxERUYQRFfxbW1vx2WefAQBa\nWlqwevVqvPbaa9Dr9T4tHBEREXmfqOD/3HPP2VMELlu2DF9//TUsFguKiop8WjgiIiLyPlEjYf75\nz3/i9ddfh8FgwL59+3DgwAFoNBrcfvvtvi4fEREReZmolr9E0rkK1uHDh5GZmWlfUc9iYY5sIiKi\nUCOq5Z+Tk4Of//znOH36NF544QUAwJtvvonhw4f7tHBERETkfaKC//Lly3H48GEkJiZi9OjRAICB\nAwfi/vvv92nhiIiIyPtEdfvLZDKMHDkSgiCgqqoKVVVVGDp0KL755htfl4+IiIi8TFTL/5VXXsHG\njRuRkpICqfTK/YJEIsHevXt9VjgiIiLyPlHB/5NPPsG+ffug1Wp9XR4iIiLyMVHd/gMHDmTgJyIi\nChOiWv733HMPnnnmGdxxxx2Ii4vr9tqYMWN8UjAiIiLyDVHB/6233gIAe5Y/Gz7zJyIiCj2igv++\nfft8XQ4iIiLyE1HBXxAEfPLJJ/jss8/Q0NCAlJQUTJo0CdOnT/d1+YiIiMjLRAX/VatWoaKiAjNm\nzIBGo0FTUxPeeustfP3113jyySd9XUYiIiLyIlHB///+7//w17/+FVFRUfZts2fPxqxZsxj8iYiI\nQoyoqX5WqxVKpbLbNpVKhY6ODp8UioiIiHxHVMt/3LhxeOKJJzB79mx7t39paSnGjx/v6/IRERGR\nl4kK/s8//zzee+89/PnPf8alS5fsA/4eeOABX5ePiIiIvExU8FcqlXj00Ufx6KOP+ro8RERE5GMu\ng//DDz+Md955B9OmTYNEInG4z65du3xSMCIiIvINl8H/l7/8JQDg97//vV8KQ0RERL7nMviPHj0a\nALBlyxaUlJT0en3WrFn46KOPfFMyIiIi8gmXwX/fvn3Yt28fDh06hBdeeKHba3q9Hv/5z398Wjii\nQDOaLGjUtyNREwWVUtQQGSKioOfyapadnQ2DwYA9e/ZgwIAB3V4bPHgwHn74YZ8WjihQrNYOrN9e\ng6PVtahvMiA1QY3xmWl4aMYoyGSi0mMQEQUtl8E/OTkZt99+O6655hqkpqYiNTUVAGA0GtHU1ISB\nAwf6pZBE/rZ+ew22HfrW/v+6RoP9/48UZgWqWPQ99sgQ9Y+oJszp06dx++23w2AwAACam5tx1113\n4W9/+5tPC0cUCEaTBUerax2+drS6FkaTxc8l8h6jyYJaXWvInoPV2oF1W49j4ap9eGzlHixctQ/r\nth6H1cpso0SeEHXL/NZbb2H79u1Qq9UAgAEDBmDbtm342c9+hjvvvNOnBSTyt0Z9O+qbDA5f0zUZ\n0KhvR1pK508nVFqg4fIYgz0yRN4h6mplNBp7PfNPTU219wQQhZNETRRSE9Soa+z9/U5JUCNRExVy\nwTQcgqa7HpkHCjKC+gaMKJiIukrl5ORg8eLF2Lt3L7744gvs3r0bCxYswMSJE31dPiK/UynlGJ+Z\n5vC18ZlpUCnl9mBa12iAIFwJpuu31/i5tO6Fy2MMMT0yRCSOqNvk3/72t/jzn/+MdevWobGxEYmJ\nibjlllvw4IMP+rh4RIHx0IxRADqDo67JgJQuLftQa4F68hgjmInpkSEicUT94qOiorBgwQIsWLDA\n1+UhCgoymRSPFGbhgYKMXs/06xoNIRVMwyVo2npkuj6+sLH1yBCROH7J7X/q1CksWLAADz74IObN\nm4eioiLU1NQgISEBADB//nxMmjQJ27Ztw4YNGyCVSjF79mzMmjULZrMZRUVFOH/+PGQyGVasWIEh\nQ4bg5MmTWLZsGQBgxIgRWL58uYenTuSeSinvFchDLZiGU9B01SNDROL5PLd/W1sbfve732HChAnd\ntj/99NOYPHlyt/3WrFmD0tJSKBQK3HPPPZg6dSr2798PjUaDkpISHD58GCUlJVi9ejVeeuklFBcX\nY/To0Vi8eDEOHjyIm2++uc/lJBIrFINpuARNVz0yRCSey19Ne3s7vvjiC6etfjGUSiXWrVuHdevW\nudzv2LFjyMrKQlxcHABgzJgxqKqqQllZGQoLCwEAubm5KC4uhslkwrlz5+xrD0yePBllZWUM/uQ3\n3gim/pwmGG5B01GPDBGJ5/LX8/zzzwMAJBIJvvvuO6hUKmg0GjQ1NcFsNmPYsGFuE/3I5XLI5b3f\n5v3338e7776L5ORkvPDCC9DpdEhKSrK/npSUhPr6+m7bpVIpJBIJdDodNBqNfd/k5GTU19e7PdnK\nykq3+3jC28cj8YKh7scMATLTEtFiiEesWgql3IQvv/yH27+zdgjYXdWMk+cMaG61Ij5GhpGD1Zg2\nJh4yad9vtD1xvh9/Gwx1H8lY/4ETTnXvMvjv3r0bALBixQr86Ec/Qn5+PgBAEAR88sknqK6u7tOb\n3nnnnUhISEBGRgbefvtt/OlPf8KPfvSjbvsIguDwbx1td7ZvT2PHjvW8sE5UVlZ69Xgknq/r3tct\n8nVbj6P8VIv9/82tVpSfasGAAdqgn3Mf6nUf6njdCZxQrXtnNyyi5vkfPHjQHviBzp6AGTNm4ODB\ng30qzIQJE5CRkQEAuOWWW3Dq1ClotVrodDr7PnV1ddBqtdBqtfZWvdlshiAISE1NRVNTk33fixcv\nQqvV9qksRDb+SB0bLnPuvY1pe4n8S1Twl8vl+Oijj9DS0tlaaWlpwdatWyGV9i2T2S9+8QucPXsW\nAFBeXo5rr70W2dnZOH78OPR6PVpbW1FVVYWcnBxMnDgRO3fuBADs378f48aNg0KhQHp6OioqKgB0\n9lDk5eX1qSxENv5I3MNENY6FUtIkonAgql/tlVdewbJly/DCCy/YB/+NHDkSL7/8stu/ra6uxiuv\nvIJz585BLpdj165dmDdvHhYtWgS1Wo3o6GisWLECKpUKixcvxvz58yGRSLBw4ULExcWhoKAAR44c\nwZw5c6BUKrFy5UoAQHFxMZYuXYqOjg5kZ2cjNze3H9VAkc5fiXtCbZqgP4Ra0iSicCDqFzVq1Ch8\n9NFHMJlMaGpqQnx8PKKixF2kMjMzsXHjxl7bp0+f3mtbfn5+t8cLAOxz+3saPnw4Nm3aJKoMRO74\nKwteKE4T9LVwyUBIFEpE9dsLgoAPPvgAjz76KJ566ilERUVh69ataGho8HX5iPzC1iJ3xNst8odm\njMLMvHRoE9WQSgBtohoz89JDbs69t/iz7omok6jgv2LFChw6dAjz5s3DpUuXAHTmALBNBSQKdWIW\n8/EW25z7Nc/egrVFt2LNs7fgkcKsoFwN0B/8WfdE1EnUr2rPnj3Ys2cPpFIpSkpKAAD33nsvNmzY\n4NPCEfmTv7PgMVHNFeGSgZAoVIi68iiVShgMBsTExNgH/BmNRtHz64lCQbhlwQslrHsi/xL167rj\njjtw33334e6770ZLSws++OADbNu2DXfeeaevy0fkd2yRBw7rnsg/RP3KnnzySfzgBz/AgQMHcO21\n16K6uhqPPPIIbr31Vl+Xj4iIiLxMVPD/y1/+gp/+9Kf2BXaIiIgodIkaXrx9+3Y0Nzf7uixEJJLR\nZEGtrjVi0wETUf+IavmPHDkSM2fORHZ2NuLj47u99rvf/c4nBSOi3qzWDqzfXoOj1bWobzIgtcuo\n+EidKkhEnhMV/AcMGIBZs2bBaDRCr9cjISEBSqXS12WjfuDqaOHJlgPfxpYDH0DQrwhIRMFDVFTI\ny8vDsmXLcOLECfu2rKwsvPjiiz4rGPUNW4bhiznwichbREWDxYsXY+7cufj8889x8uRJlJeX4557\n7sFTTz3l6/KRh7g6WvjiioBE5C2il/SdNWsWNBoNACA+Ph733nsv5HK2MoIJ14oPb8yBT0TeIir4\nT548GTt37uy2be/evZgyZYpPCkV9w5ZhJ3cj4UN1pDxz4BORt4i6Wnz22Wf4y1/+gqVLl0Kj0aCp\nqQlGoxGDBg3C3r177fvt2rXLZwUl9yJ9rXh34x3CYTwEc+ATkTeICv5LlizxdTnICyJ9rXh3I+HD\nYaQ8c+ATkTeIumrceOONvi4HeUmktgzdjXeYfet1YTVSvi858Dn9k4hseAUIM5HaMnQ33uFMrd7t\neIhwXVAmHB53EJF38ZcfpjpbhjEREfgB9yPhh6ZpInakPKd/ElFPDP4UFtyNhI+PjYrIkfLhPP0z\nVGdthBt+DqEpPK94FBT8/YzZ3XiHSBwPIWb6Z6g97uBjjODAzyG0hdavnkJCoC4K7sY7ROJ4iHCc\n/hkOszbCAT+H0MbbM/K6QD9jdjfeIZLGQ4RbYqBwfowRSvg5hD4Gf/IqXhSCz0MzRmFmXjq0iWpI\nJYA2UY2Zeekh+biDWSyDAz+H0Bdat/0U9MLxGXOoC6fHHeH4GCMU8XMIfWz5k1dx8ZngFS6POzKH\npTjcHoqPMUJVuD1OikT8hMirIj3FMPlG10GkdY0GqKNkACRoN1kiYtZGMLp/+gi0Gsz46nQ9GpqN\n/BxCDK/E5HWhPKUuVFLghko5vaXnyHJDuxUAMCVnCB6/e3RE1EGw6DmbJyVBjUljh+DRwkzEqJWB\nLh6JxF8MeV0oPmMOlTnLoVJOb3I1iPT4Nzo/l4Z63ojVNxqwr+IsYtUKTvELIeF5taCAsmX8AhAy\nz5gDPT1RrFAppzdxZHnw4Gye8BH8V2UKGaHaKnV3QfPnin+uuvODqZz+xJHlwYOzecIHPyXymlDN\n+BUMFzQxN07BUM5A4CDS4MEbsfARvM0x6hd/L7YRyt2BwTA9UUx3fjCUM1DCKVFRKOMUv/DBTyrM\n9KXr3d3IcTEjy0O5VRrolqXY7vxAlzOQQnEQabgK5dk8dAV/PWHGk653dzcKntxIhHp3YCAvaLom\ng8N6s73W9cYp0i+8nYmKeNkKJN6IhQd+YmHE0wFh7m4UPLmRCPVWaSAvaNsd1JlNzxsnXngpWPBG\nLLTxmX8Y8WRKlLsbheaWdo+f4YfDc1l/p8A1miyoOHHR6es5GQMcliVcUvUSUWD45cpx6tQpLFiw\nAA8++CDmzZuH2tpaPPvss7BarUhNTcWrr74KpVKJbdu2YcOGDZBKpZg9ezZmzZoFs9mMoqIinD9/\nHjKZDCtWrMCQIUNw8uRJLFu2DAAwYsQILF++3B+nEtQ86Xp3d6Nwplbv8TN8tko95+pzAIAZeeku\n/z7SMv0RkXf4vOXf1taG3/3ud5gwYYJ92+uvv465c+di06ZNuPrqq1FaWoq2tjasWbMG7733HjZu\n3IgNGzagqakJn3zyCTQaDT788EM8/vjjKCkpAQC89NJLKC4uxubNm9HS0oKDBw/6+lSCnicjcd2N\nHB+apunzyHK2SsVz9TloE9VIcfKa1dqBdVuPY+GqfXhs5R4sXLUP67Yeh9Xa4cviElGY8HnwVyqV\nWLduHbRarX1beXk5pkyZAgAUSgKYAAAgAElEQVSYPHkyysrKcOzYMWRlZSEuLg4qlQpjxoxBVVUV\nysrKMHXqVABAbm4uqqqqYDKZcO7cOYwePbrbMUh817u7G4X42ChO6fGDvk6disRMf0TkPT6/gsvl\ncsjl3d/GYDBAqexcACI5ORn19fXQ6XRISkqy75OUlNRru1QqhUQigU6ng0ajse9rOwZ51vXubuR4\npI8s9xdP6zlSM/0RkfcE/AohCEK/tzvbt6fKykrxBQvA8XzhvJvXxwwBMtMS0WKIR6xaCqXchC+/\n/Ifo1wMlFOreE57U86XLFqdTA+sbDTh0pBJJcb77aYdb3Yca1n/ghFPdByT4R0dHw2g0QqVS4eLF\ni9BqtdBqtdDprqzQVVdXh+uvvx5arRb19fUYOXIkzGYzBEFAamoqmpqa7PvajuHO2LFjvXYOlZWV\nXj0eiRfpdW80WbD58D6HNwCpiWrk5Y4V1fLvy2DBSK/7QGP9B06o1r2zG5aATPXLzc3Frl27AAC7\nd+9GXl4esrOzcfz4cej1erS2tqKqqgo5OTmYOHEidu7cCQDYv38/xo0bB4VCgfT0dFRUVHQ7BlEk\n6G+KVQ4WJCKft/yrq6vxyiuv4Ny5c5DL5di1axf+8Ic/oKioCFu2bMGgQYNQWFgIhUKBxYsXY/78\n+ZBIJFi4cCHi4uJQUFCAI0eOYM6cOVAqlVi5ciUAoLi4GEuXLkVHRweys7ORm5vr61MhLwi1qWnB\nWt7+jMcI1QWYiMh7fH41y8zMxMaNG3ttf/fdd3tty8/PR35+frdttrn9PQ0fPhybNm3yXkHJp0Jt\nud9gLq/thuSBggyPcypwsCARAUEw4I8ig79bm/1tsQdj69gbNyShvAATEXkPf+Xkc/5sbXojQAZr\n69gbNyShvgATEXlH8PW3kt8ZTRbU6lod5uv3Bk/WHOgvbyS/8Wd5xXJ3QyL2s+N67EQEsOUf0fz1\nXNtfrU1vtdiDsXXsze56Jm8iIgb/COav59r+Wu7XWwEyGJcn9uYNidnagTt+nI7Zt16HNqMl6GYy\nEJHv8Rcfofz9XNtbrU2jyYJLly0wmiy9yufNABlsrWNv3JC46ukhosjC4B+h/D3quz/L/RpNFuia\nDNh+6FtUnLiIukYDNh/e1+sRhTdb7MG4PHF/b0iCcQYDEQUGg38QCEQimUA911Yp5UjU4Pvzhcvz\n7dpS7VlOZ4HL2y32zuWJg+Nn0t8bqGCcwUBEgcFfewAFMpFMIJ5re3K+RpMFaz/+Cnsrzro85mdf\nncfsW69DfGznzUowtti9rS83JJzfT0Rd8dceQIHuhn1oxihYrB04Wl2LRn07UhN9+wxYzPnabhDK\nqmtR72Tluq4amo34Zcl+jM9Mw4y8dKQkqKFSyoOqxR4MgnEGAxEFDuf5B4i35m33lS3IVpy4iMbL\n7UjSqJCTMcBnvQ5iz9d2gyAm8Ntc0rdjx5EzeOKVfVykxgnO7yeirviLD5BAd8P2bIU36I3YceQM\n5N93m3ubmPNN1MDpDYJYHMTmXLDNYCCiwGHwD5BAdsMGYvCXmPN1dYPgKQ5i6y0SxkMQkTjs9g+Q\nQHbDumuFX2ho9Xq6XzHna7tB8IZApeENBZ3jIWIY+IkiGH/9AeSLblgx0wZdtcKjlHL89p2j0DUb\n3c4+8HSKorvzdTUDQaWUwWS2IiVBDalgxoUm1zcmwTiILRBTOomIHOEVKIC82Q3raBpdTsaAbiPg\nbVwFWUO7BYb2zsDq7Pl5X6coijlfZzcI908fgeZWMxI1Ufjq2Jc4di7K4fx/G097T3wZmAM5pZOI\nyBEG/yDgjWlpjqbR7ThyBjuOnIE2sXewcRRkL7eZYGi39jp2z+fn/Z2i6Op8Xd0gRKuVnftIJfZ9\numb+60vvidjA3J+bg0BP6SQi6onBP0R1DUaA61HyjoJNzyDbbrbilyX7Hf5919kH7gYLemuxGDE3\nRCqlHD/QxuGJu7P7HJzdBeb+ttqZWY+IghGvOiHGUTDKGpYiapS8o2BjC7JGk0XU7ANXgwXrGg14\nquQALl12P17A2/rSeyImMG/ccaJfrfZAT+kkInKEDxxDjK2lWtdogCB0BqO9FWdFtR5djYAXO/sg\nUROFlHiV0/do0Bvt5dp26Fus314j4qzE67qqX3+JmfXQ30RMrmYweDoo0WiyOJyF4Ww7EZEzbHKE\nEFctVUBw+/fugs3900eg1WDGV6fr0dBsdPj8XKWUIy5aifomo6gye6tru+ciP45W9fO0699d7gFA\n0u9Wuy+X4v1ZQQY27DjBgYRE5DEG/xDiqqVqbLfilpwhqP5G53QE/I2jBtqDTddAqZBJuwWXlAQ1\nJo0dgkcLMxHz/SA7+/uYLGgxmEWXua7RO13brp7NPzRjVJ+ey7sLzAOTo72SiMlXS/FWf6PDt+f1\nvbYDHEhIRK4x+IcQTYwCKqXM4Yj81EQ1nrh7NABgTekxHKj8zuExHLUiY9WKbkGkvtGAfRVnEatW\n9AoifcnCp1L0rRVqu0GJVslddr9brB3YceSMfZsnQdBVYJbJpF5Z+dBXS/GeuaB3uJ0DCYnIHV4d\nQsimXf90GPiBK8GozWBCefUFh/t8XnMBHR1Cr0DprKfAURBx1VXuzIYdJ7BozhiX+7jqiUiMi8Il\nJ2MV6hsNTs/XVRDs+n6uArM3EzF5eyneDidrF3EgIRG5w6tDiHDVAlRHyXH/9BEAgLe3VtuT9PTU\nGSjFL5zjLIhkDUvB3oqzoo/z1el6GE0Wh0FYTE+Es8APdN6MXLrsePyBo/K7mrqXlhIDoPfYgUDm\nw3d1syWVOr4BCMbshkQUXBj8vcTXqVtdtQAN7RZcutwOqUyKr07XOz1GoiYKDR7ku+8aRHoGTXWU\nHIAAQ7sV6igZTOYOWDscDzpsaDY6bYk6ep7tSa+CJlqJppZ2CA7e2lEQ7OvYAW8kYuoLV+MShg7U\ndLtJsuESvUTkDq8Q/eSv1K3uutu3H/oWhTcPh67Z+Sj8UenJ+Oyr8067i3vqGkR6Bk1b78IPtLH4\nrq7F9YEkwNaDp/Gzggx7il6V0nXCIGeS41W41GxEamLvHgJX5Qfcz+vvz9gBX3L26KHraH8u0UtE\nnmDw7yd/pW5VKeXIyRjQLTh1VXHiIuZOH+n0BkEdJcPdtwzHoS/PO32P5HgVGvW9p/i5CprndW4C\nPzq7pnccOYP9ld/ZkwmNz0zDbblDPRo8qE1U44+LbsbnFV/ixpzr8av/OuBwPwmAaeOu6hUE3c3r\nD9ZMfK4GDHKJXiLqC14p+sHfqVunj7/aafDXNRnQZrTgxlED8cnhf/V6fcoNV2FwahxSE1QO5+in\nJqjwX7+a5DA1b18GnTnSc8EgfUs7UhLUqBfZzT8+Mw3xsVFIipOj8XK701wDAoCKE3VYv72mWw+M\nq96TRI0KDU56TYJlAJ2zRw+BeiRBRKGLmUD6QUzqVjHcZWizWjuwbutx/P7dz50eIyVBjfgYBaq/\nbXC6j0opx4SsQQ5fm5A1CPGxUQ7XeXeVpU7aj2/QgX+cw+U2k8PX0gdpoE1UQyrpbPHPzEvHQzNG\nwWrtwKcVTVj+TpnLYzfojb0yDLrKYjhu1EBoE72TiY+6YwZCouDD5kI/uMsQ5y5guBsvYBtEuPXg\naactfpvxmWnYsOMEzjh5Bv55zQX87PYf9mnqWl8GnYll/H7qojpKjnaTxV6eudNHfN+yFzAw+coN\nybqtx1F+yv2jBpuePTCuzl8uk/Z7Tj9dwaWMiYIXr2j90N/Urc7GC3QIAqQSiT2VravWdWqCChOy\nBmHu9BFYsGqf0/2udF3H9Ok58bzpI3Cg6jvoW6+01DUxSrz02AR8uOdr+wXe0ah7MWLVcqz6xY+h\nTVDjg13/xC9LDvQKGGZrh8cDBHt22bt6fu7NOf3EpYyJghmDfz/1NWC4Gi+w94uz3ebqO3uuLpEA\nSx8ej6Fp8ajVtbqZD6/q1hPh6XPiojc/6xb4AUDfasLzb5XhtcWT8UBBBi40tGL5O0ehE5n3vytd\nkxFRCjk+2PVPpwHjjh+ne5xd0FkPjKPz708mPuqOSxkTBTf++vqprwHD3bx9MZI0KiTGda6wl6iJ\ngjbR+VTAcV3y+nuquaXdaSrZMxf0aG5pR6xagb+X/wctTp7hX5MWhxaD2ekgPVWUzG0a39m3Xudx\ndsGcjAEenzcH0PUflzImCm588OYlnQGj92A5Z1wNohOrodmIp1cfxLqtx6H4Pg+9I5oYJeb3seva\naLKg8mSd096Hjg7gTK3e3sVrNDne8eo0DbKvTXXxTpLvR/A7DxiX20yIVSs8Kv+MvHSP9ifv8OZS\nxkTkfQz+AeJq5Lk6SuZwu1TSe5utW3z99hrcP30Ehmhje+2jbzXhzY+/cjja2tlIbNsMg4Wr9mH1\n5iqn5yGVdPZAuHsWf6DqHPZ84TwlcLvJAkBwGTC2H/rW4eBCmaOKQecsgZR+3mBR37j6fnMAJVHg\n8RcYQM7GC3QIgsO5+k6y5wIA/v75f3Dk+Hmnz9v3VpzFP07VYXxmGh79frCVq5HYb2897naGga1M\nz//3YTRedtzdL1ZKghoDk2OcDqDMyRiAihMXHf6tUiF1uOARg0xgcQAlUfDilTGAnI0XsFo7uo32\nF8PQbnE7VuCSvh07jpzByTOX8MP05G43GF1nGpjNVvz98/+IPo/+Bn7gSqB2FjBuyx2KT8vOOPxb\nY7sVt+QMQfU3OgaZIMIBlETBKyC/xPLycjz11FO49tprAQDXXXcdHn74YTz77LOwWq1ITU3Fq6++\nCqVSiW3btmHDhg2QSqWYPXs2Zs2aBbPZjKKiIpw/fx4ymQwrVqzAkCFDAnEqXmEbYGbrgrctMzv7\n1uvwyz/sx6XL4hfjEePb83qc17U6fO3TI/+C1YOsff0llQL544faA7UtYMy+9TqcqdVjaJoG8bFR\n9rTAjm6GUhPVeOLu0QDgNMj4euElco4DKImCT8B+kTfeeCNef/11+/+fe+45zJ07F7fddhv++Mc/\norS0FIWFhVizZg1KS0uhUChwzz33YOrUqdi/fz80Gg1KSkpw+PBhlJSUYPXq1YE6lX5zlgzlttyh\nXg/8NkZT725yAH4N/EBn4H/i7uwr7+8iMYyYnAo9gwwTzRAR9RY0t+Pl5eVYvnw5AGDy5MlYv349\nrrnmGmRlZSEuLg4AMGbMGFRVVaGsrAyFhYUAgNzcXBQXFwes3N7gLBmKxdrhNBe/TWqCGi0Gk8Nn\n3oGmUsqc3mRoEx13zbtKDHP/9BFoNZhR8f/O4bKhQ1T3PhPNEBH1FrDgf/r0aTz++ONobm7Gk08+\nCYPBAKVSCQBITk5GfX09dDodkpKS7H+TlJTUa7tUKoVEIoHJZLL/vTOVlZVePYf+HM9k6UCLoQNR\nCuBgVb3DfY4cO4vhaSrUNzk+RvbQaNx+YwL2fql3mPI2KVaGSy2Og69CBph9fL9gNFm7vY9SDmQN\njcaEEXHQxMiglJvw5Zf/sO9vsnTgYJXjQX27yv6FA5VnoG/rgCZaitFDo5E/Nh4qZfdjdOXqeP9X\n9W9kphmhlLP17ylv/47IM6z/wAmnug9I8B86dCiefPJJ3HbbbTh79ix++tOfwmq9EokEJzliPd3e\n09ixYz0vrBOVlZVuj+foOXPPbuikOBWaWx1HYX2bFfPvHoeBn/0Le7/4j711r46SY8oNQ/DwzEzI\nZFLcmHPlmLomA5LjVYiLVuKywQzA8YBBsxWIUnTeOLWbrEiIU3pl4J6j97ExWYD4hGSMv3GUw9UD\na3Wt0Lc5XnK43SKg3dL5OevbOvDlv9pw1Q8Gumy9uzqevs2KocN+iLSUmD6clf8Fy5gFMd978h3W\nf+CEat07u2EJyFVkwIABKCgoAABcddVVSElJwfHjx2E0GqFSqXDx4kVotVpotVrodDr739XV1eH6\n66+HVqtFfX09Ro4cCbPZDEEQ3Lb6/cnVc+ae3dANeudd+ikJnfPUH7trNO6bOgKnzjYhPkaBqwZq\nugWAnoPkDn15DruO/tttOdvNnQ/4B6fG4OUnJuLxV/Z69Pjg6oFxuGZwPI5W19oX6HFnX8VZHKg8\niw6he9e/TCZ1uVCSI+7SxPZ34aVgwDELROQLAQn+27ZtQ319PebPn4/6+no0NDTgJz/5CXbt2oU7\n77wTu3fvRl5eHrKzs7FkyRLo9XrIZDJUVVWhuLgYLS0t2LlzJ/Ly8rB//36MGzcuEKfhlKtn+M7m\nqjsyPjMNCpkU67Yed3jxN1s7cKGhDR1WK3aV/wcVJy66XQjIkXP1rdiy5xQmjfkBPi1zf9NgY2i3\nYOE92VApZdjpwd/Z8hX0fP7uaqEkR9ylie3vwkvBgGMWiMgXAnL1u+WWW/DrX/8ae/fuhdlsxrJl\ny5CRkYHf/OY32LJlCwYNGoTCwkIoFAosXrwY8+fPh0QiwcKFCxEXF4eCggIcOXIEc+bMgVKpxMqV\nKwNxGg65WtCkvOYCGprdL3qjUsowbdzVuH/6CLzxP19ib8WVzHi2i/+xr+tR19jmsKXuLBWvK38v\n/zc0sZ0tYanEdUIhG12TARcaWlF5ss7zN+yiawu+6zx/dz0AYlrvoZxohovjEJGvBOTKERsbi7Vr\n1/ba/u677/balp+fj/z8/G7bbHP7g5GrBU0amo2iAqvJbMVXX9e7zNj37wuX+1vUbsxWwX5jIibw\nA53B9+O9X6Peg4V2HKlrNGDtx1/hF7Ovtz/CuPOmYXj45b+7XCJYTOs9lBPNcHEcIvIVPjT0MncL\n9ogJrB0CcObC5T4tjetP0VFyHPjHOa8ca2/FWazfXmP/f21Dq8vAPyHLs9a7pwsvBQMujkNEvsLg\n72WuFjQJN+d1vacX9sfR6lr7AkND0zQuxy4svCc77Ae8cXEcIvKV8L56BshDM0ZhZl6609X5woFK\nKYPJIvL5gEj1jZ1d2QAQHxuFoQM1DvcbmCBHfGz/W73OVjQMJrbvkjZRDamkc4bEzLz0kBizQETB\ni00HH5DJpHigIANl1bUwtPfveXjw8m7gBzq7ubt2Zb/6izw888YhnLmgR0dH5zoAQwdqMOfHvZct\n9kQoTZ8L5TELRBS8eBXxkUZ9O3ROBmuFMnWUDBOyBmFflxkI3pI1LKXb/5VKOV5bPBnNLe3dFvnp\nb5atUJw+x8VxiMibgquZE0bcDfwLRgoRTyli1Qo8NGMUUhNUXn1vmRQ4+I9zWLBqH/7rwyq0Gq5k\nG4yPjUL2tale6+p3NX0umB8BEBF5C4O/jyhkUqeL2gQjqbQzsLvT0GxEm9GCCVmD+vxeQ9Pi7M+w\nVcrOOw7baoL1jQbsqziLn/9uN9ZtPQ6rl5cZFDN9jogo3LEf0Ufe3noc+lbv58r3FYVchsYWs9v9\nkuNVSNRE4f7pI7C7/AyMJs+Cc/ogDf646ObvsxO24rfvHHV4k2Rot9q74r35vDscUv4SEfUXg78P\nuOpaDlZmsxVJmihcctPyjVYpoFLKvx8l7zzwKxUSmMwCpNLOjIPJGhXGZQ7Eo4VZkMmkkMmkiFLI\noXOT8fDvn/8bZd9n57MNzMse3PfBhuGQ8peIqL94pfOBRn272yAabKKUMsSpFW7LXdvQOTUuWiW3\nB3ZHTGYBt+QMwUMzHK/gB7huhdsY2q32GRO2gXkXr4vFjTd4dn5dhXLKXyIib2Dw94FETRS0ieJX\npwsGhnYr/n3RfdIek7mzuz5KIXe7hkD1NzpEKWVOB+p5upCPzT/PGWA0WfrcSuf0OSKKdBzw5wMq\npVzU4LnQJUGiJgoJsa7Psa7R/QC6KwmRxAff5larVwbmhWLKXyIib2Dw9wGjyYLmluDOy99X6igZ\nBiZHQ6WUI/s6rct9k3ok7XHE1gp/74WpmJIzBKkJKkglQGqCyukNQXyMjAPziIj6gU0eL2szmPBf\nm/+BBn3ojPT3xJQbrrK3lOffMQqHvzwPq5PVijwZQBetVmLRnDEwmiz2rviNO044fCQwYrCarXUi\non7gFbQfugYqhUyK9dtrsLPsX17PeR9ItlH7qQkqTMgahIdmjOqWHtdZ4B86SINHXWTL61p3XQN5\n10x2zgbmZQ8OrcGURETBhsG/D6zWDnxa0YQ3P91nzw0frZLjTO3lQBfNqwanxKBk0U3Qt5q7Bel1\nW487HaSXpInC+Mw0+5Q+G1uw18QosGnXP0Xl1Xc2MK+/6X2JiCIdg38frN9eg/JTV0bGh9Kofk+c\nb2jFX3ac6BbIXeUwSNJE4fXFk7uN7u+5iI5KKYOh/UpSHzF59ZnXnojIuzjgz0OhmMCnrwQB2HHk\nDNZvr7Fvc5Uet+lyO9qM3XPj2xbRqWs0QBDQLfB3xbz6RET+w+DvIVfBL1x1DcxRCiminKwAlPL9\n44/O7H8Wj26UmFefiMh/2JfqITFZ6cJNfaMBuiYDPj1yBn///N9OFyyKVSvw9OqD9mf5mcNSRNcT\n8+oTEfkPW/4eUinlyMkYEOhi9JuY5XttEjVR2H7oW2w79K3TbnuZVIJvz+vt3ft136/Op44S90bM\nq09E5D8M/n1QMHFooIvQbzFqJWQiP/0bMgag4sRFl/s4m/IHSBxuVUfJIZUA2kQ1ZualM68+EZEf\nsanVBzs+OxPoIvRbU4u4JETpgzQonDQcuz//T5/ep91kwZScITj+ja7bXP37p49Ac48phERE5B+8\n6nrIaLK4bQWHEnWUHNFR0l4ZCVVKGSaP/QEeu2s0zNYOt+Mc1FFyGNp7j9ZPSVDj8btHA0CvpD7R\naqUXz4SIiMRi8PdQo749rAb7GdotUEdFQQIgOUGFzPQUFE5Kx+DUOHuQlsmkTlffU0fJMfXGq9Ah\nCPjk8L96vd71WT7n6hMRBQdejT0UrQq/Krv0/RQ7XZMRB6q+gyZG2SvhzkMzRsFi7UB5zQU06o1I\njldh9PBUPFqYiWi1ElZrB6QSSa9UvHyWT0QUfMIvkvlY4+Xwn4t+tLoWDxRkQKWUw2iyQNdkwPZD\n36LixEU0NBuRpInCDT8c2C3zn7NUvEREFHx4dfZY+Cza44yu6cq8/qPVtb0ec1zSt2PHkTOQfx/w\nu2IqXiKi4Mepfh6KcbLGfDhJSVDb5/W7Gt/AlLxERKGJwd9DxWuPBLoIPpcjYl4/wJS8REShisHf\nA80t7bjQ0BboYnidVIpuCXdm5KWLWr+AKXmJiEJT+Pdhe9GZWn2gi+ATedmDcX9+hn2QntFkEbV+\nAVPyEhGFJrb8PaCUh051RSmkmD7uKiR93zKXOim6OkqGJ+4ejbSUGHsgVynlGJ+Z5vTYTMlLRBTa\n2GzzwO7yM4EugmhTx12Nx+4aDaPJgkZ9O7YePI0dR8703u/GqxHjINOeLbB3nbefkzEAM/LSkZKg\nZoufiCiE8Qruga9O1we6CG7JpMBtudfg4ZmZAK5MvXu0MAtymVR0Eh7O2yciCl+8mnugrjH4RrYn\naaLswTlrWAqeuHu0w5Z8X4M55+0TEYUfXtVDmDZRjT8uuhltRguDORERiRbSUeDll1/GsWPHIJFI\nUFxcjNGjRwe6SH41PjMN8bFRiI/ldDsiIhIvZIP/559/jn//+9/YsmULvvnmGxQXF2PLli2BLpZf\nqKPkmHLDEI62JyKiPgnZ4F9WVoZbb70VADBs2DA0NzejpaUFsbGxAS6ZbxTkDsVtudcAEDAwOYaD\n74iIqM9CNoLodDqMGnWl5ZuUlIT6+nqXwb+ystIfRfMKiQQQBCAhRoYRg9UYe5UZDee/BgA0nA9w\n4YJAKH2W4YZ1H1is/8AJp7oP2eDfkyC4X21v7Nix/XuTTd/17+8diFHJ0WrsvTjObROGovDm4Zxi\n50BlZWX/P0vqE9Z9YLH+AydU697ZDUvIRhWtVgudTmf/f11dHVJTU336nh+tuB2znvvfPv+9UgFc\nkxaPn0weDoVCgeuGJCBWrcD67TUO59/LZKGTUZCIiEJHyAb/iRMn4o033sB9992HmpoaaLVanz/v\n97QF/sOhiZh/ZyYGJMW4nI7HZDpERORPIRtlxowZg1GjRuG+++6DRCLBiy++6Jf33bpqBtZvr8G2\nQ9/at/0gNRppqXE4c16PhmbHrXd30/E4/56IiPwlpKPNr3/9a7+/py1TXmaaEUOH/bBbS92WR5+t\ndyIiCmaMUH2klEuRlhLTbRtb70REFAo4ooyIiCjCMPgTERFFGAZ/IiKiCMPgT0REFGEY/ImIiCIM\ngz8REVGEYfAnIiKKMAz+REREEYbBn4iIKMJIBDFr4YaBcFqHmYiISCxHSxFHTPAnIiKiTuz2JyIi\nijAM/kRERBGGwZ+IiCjCMPgTERFFGAZ/IiKiCCMPdAFCzcsvv4xjx45BIpGguLgYo0ePDnSRQt6p\nU6ewYMECPPjgg5g3bx5qa2vx7LPPwmq1IjU1Fa+++iqUSiW2bduGDRs2QCqVYvbs2Zg1axbMZjOK\niopw/vx5yGQyrFixAkOGDMHJkyexbNkyAMCIESOwfPnywJ5kkFq1ahUqKythsVjw2GOPISsri3Xv\nBwaDAUVFRWhoaEB7ezsWLFiAkSNHsu79yGg04o477sCCBQswYcKEyKt7gUQrLy8XHn30UUEQBOH0\n6dPC7NmzA1yi0Nfa2irMmzdPWLJkibBx40ZBEAShqKhI2LFjhyAIglBSUiJ88MEHQmtrqzBt2jRB\nr9cLBoNBuP3224XGxkbhr3/9q7Bs2TJBEATh0KFDwlNPPSUIgiDMmzdPOHbsmCAIgvD0008LBw4c\nCMDZBbeysjLh4YcfFgRBEC5duiTcfPPNrHs/+d///V/h7bffFgRBEL777jth2rRprHs/++Mf/yj8\n5Cc/ET7++OOIrHt2+3ugrKwMt956KwBg2LBhaG5uRktLS4BLFdqUSiXWrVsHrVZr31ZeXo4pU6YA\nACZPnoyysjIcO3YMWVlZiIuLg0qlwpgxY1BVVYWysjJMnToVAJCbm4uqqiqYTCacO3fO3itjOwZ1\nd8MNN+C1114DAGg0GqqTnVwAAAYwSURBVBgMBta9nxQUFOCRRx4BANTW1mLAgAGsez/65ptvcPr0\naUyaNAlAZF5zGPw9oNPpkJiYaP9/UlIS6uvrA1ii0CeXy6FSqbptMxgMUCqVAIDk5GTU19dDp9Mh\nKSnJvo+t7rtul0qlkEgk0Ol00Gg09n1tx6DuZDIZoqOjAQClpaW46aabWPd+dt999+HXv/41iouL\nWfd+9Morr6CoqMj+/0isez7z7weByRF9zlkde7Kdn5Nre/bsQWlpKdavX49p06bZt7PufW/z5s04\nceIEnnnmmW51xbr3na1bt+L666/HkCFDHL4eKXXPlr8HtFotdDqd/f91dXVITU0NYInCU3R0NIxG\nIwDg4sWL0Gq1Duvett12h202myEIAlJTU9HU1GTf13YM6u3QoUNYu3Yt1q1bh7i4ONa9n1RXV6O2\nthYAkJGRAavVipiYGNa9Hxw4cAB79+7F7Nmz8dFHH+HNN9+MyO89g78HJk6ciF27dgEAampqoNVq\nERsbG+BShZ/c3Fx7Pe/evRt5eXnIzs7G8ePHodfr0draiqqqKuTk5GDixInYuXMnAGD//v0YN24c\nFAoF0tPTUVFR0e0Y1N3ly5exatUqvPXWW0hISADAuveXiooKrF+/HkDn48S2tjbWvZ+sXr0aH3/8\nMf7nf/4Hs2bNwoIFCyKy7rmwj4f+8Ic/oKKiAhKJBC+++CJGjhwZ6CKFtOrqarzyyis4d+4c5HI5\nBgwYgD/84Q8oKipCe3s7Bg0ahBUrVkChUGDnzp3485//DIlEgnnz5mHmzJmwWq1YsmQJzpw5A6VS\niZUrVyItLQ2nT5/G0qVL0dHRgezsbDz33HOBPtWgs2XLFrzxxhu45ppr7NtWrlyJJUuWsO59zGg0\n4vnnn0dtbS2MRiOefPJJZGZm4je/+Q3r3o/eeOMNDB48GD/+8Y8jru4Z/ImIiCIMu/2JiIgiDIM/\nERFRhGHwJyIiijAM/kRERBGGwZ+IiCjCMPgTUb+8//77WL16tct9vvrqK8yfP7/P7/Hdd9/hhz/8\nYZ//noi641Q/Igp63333HaZNm4b/9//+X6CLQhQWmNufiJz69NNPsWbNGlgsFmi1Wvz+97/H3/72\nN1y8eBEnT57EHXfcgcuXL+PChQt46aWXUFNTg1/96lcAgJkzZ2LXrl1YsmQJAGDJkiX4+9//jjfe\neAONjY32YyQmJuLNN9+EVqvFt99+i+effx5NTU2wWCx46qmncMcddwSyCojCErv9icih8+fP44UX\nXsCaNWuwc+dOTJo0CUuXLgUAHDx4EG+//TYefPDBbn/zwgsv4MEHH8Tu3bsRGxuLM2fOODz2zp07\nUVxcjD179iA5ORkff/wxAGDVqlWYPHkyPv30U7z88st4/vnnYTabfXmaRBGJwZ+IHPrss88wbtw4\nXH311QCAWbNmoby8HBaLBdnZ2d2WOwU6U9bW1NTYW+r333+/09XNcnJyMHjwYEgkEmRkZNgXuXnz\nzTftYwPGjh2L9vb2oF8alSgUsdufiBxqbGzstkZ5XFwcBEFAY2Mj4uPje+3f3NwMiURi/xuFQoHk\n5GSHx46Li7P/WyaTwWq1AuhcZfC///u/0djYCIlEAkEQ0NHR4c3TIiKw5U9ETiQnJ3dbprS5uRlS\nqRSJiYkO94+NjYUgCDAYDAAAi8WCS5cuiX4/s9mMRYsW4YknnsCuXbuwbds2SCSS/p0EETnE4E9E\nDk2cOBEVFRU4e/YsAGDz5s2YOHEi5HLHHYYxMTEYNmwYPv30UwCdqwZ6ErwNBgPa2tqQmZkJANiw\nYQMUCgXa2tr6eSZE1BODPxE5NHDgQPz+97/HggULkJ+fjy+++AK//e1vXf7Niy++iLVr1+L2229H\nW1sbBgwYIPoGQKPR4OGHH0ZhYSEKCwtx1VVX4dZbb8Xjjz9u700gIu/gPH8i8ipBEOwBf/z48Xjv\nvfcwcuTIAJeKiLpiy5+IvOaXv/wl1q1bBwAoKyuDIAgYOnRoYAtFRL2w5U9EXvPNN9/gueeeQ3Nz\nMxQKBZ555hncfPPNgS4WEfXA4E9ERBRh2O1PREQUYRj8iYiIIgyDPxERUYRh8CciIoowDP5EREQR\nhsGfiIgowvx/v82+GHKQoUMAAAAASUVORK5CYII=\n", 554 | "text/plain": [ 555 | "" 556 | ] 557 | }, 558 | "metadata": { 559 | "tags": [] 560 | }, 561 | "output_type": "display_data" 562 | } 563 | ], 564 | "source": [ 565 | "pred = reg.predict(X_test).astype(int)\n", 566 | "\n", 567 | "temp1 = y_test.values > 0\n", 568 | "# plt.axis((0,1000,0,1000))\n", 569 | "plt.scatter(y_test.values[temp1], pred[temp1])\n", 570 | "plt.xlabel(\"original\", fontsize=12)\n", 571 | "plt.ylabel(\"predictions\", fontsize=12)\n", 572 | "plt.show()" 573 | ] 574 | }, 575 | { 576 | "cell_type": "markdown", 577 | "metadata": { 578 | "colab_type": "text", 579 | "id": "AE5vNO_eueCR" 580 | }, 581 | "source": [ 582 | "## 2. Cat Boost" 583 | ] 584 | }, 585 | { 586 | "cell_type": "code", 587 | "execution_count": 0, 588 | "metadata": { 589 | "colab": { 590 | "autoexec": { 591 | "startup": false, 592 | "wait_interval": 0 593 | } 594 | }, 595 | "colab_type": "code", 596 | "collapsed": true, 597 | "id": "ReF1DjVNxhOx" 598 | }, 599 | "outputs": [], 600 | "source": [ 601 | "models.append(\"cat boost\")" 602 | ] 603 | }, 604 | { 605 | "cell_type": "code", 606 | "execution_count": 0, 607 | "metadata": { 608 | "colab": { 609 | "autoexec": { 610 | "startup": false, 611 | "wait_interval": 0 612 | } 613 | }, 614 | "colab_type": "code", 615 | "collapsed": true, 616 | "id": "yqYXcoVBusGS" 617 | }, 618 | "outputs": [], 619 | "source": [ 620 | "model = CatBoostRegressor(iterations= 440 , depth= 8 , learning_rate= 0.1 , loss_function='RMSE' , use_best_model=True)\n", 621 | "model.fit(X_train[:90503], y_train[:90503] , eval_set=(X_train[90503:], y_train[90503:]),plot=True)" 622 | ] 623 | }, 624 | { 625 | "cell_type": "code", 626 | "execution_count": 48, 627 | "metadata": { 628 | "colab": { 629 | "autoexec": { 630 | "startup": false, 631 | "wait_interval": 0 632 | }, 633 | "base_uri": "https://localhost:8080/", 634 | "height": 52, 635 | "output_extras": [ 636 | { 637 | "item_id": 1 638 | } 639 | ] 640 | }, 641 | "colab_type": "code", 642 | "executionInfo": { 643 | "elapsed": 1213, 644 | "status": "ok", 645 | "timestamp": 1519122924101, 646 | "user": { 647 | "displayName": "Pawan Bansal", 648 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg", 649 | "userId": "102337886470920224775" 650 | }, 651 | "user_tz": -330 652 | }, 653 | "id": "lBWm2szKwBEl", 654 | "outputId": "bd21f432-ee9c-462c-fcca-e854140fd6e3" 655 | }, 656 | "outputs": [ 657 | { 658 | "name": "stdout", 659 | "output_type": "stream", 660 | "text": [ 661 | "Training score - 0.9466853308679932\n", 662 | "Test score - 0.827240593918934\n" 663 | ] 664 | } 665 | ], 666 | "source": [ 667 | "y_train_pred = model.predict(X_train)\n", 668 | "y_pred = model.predict(X_test)\n", 669 | "\n", 670 | "train_score = r2_score(y_train , y_train_pred)\n", 671 | "test_score = r2_score(y_test, y_pred)\n", 672 | "\n", 673 | "training_scores.append(training_score)\n", 674 | "test_scores.append(test_score)\n", 675 | "print(\"Training score - \" + str(train_score))\n", 676 | "print(\"Test score - \" + str(test_score))" 677 | ] 678 | }, 679 | { 680 | "cell_type": "markdown", 681 | "metadata": { 682 | "colab_type": "text", 683 | "id": "lJFgf_2t04zZ" 684 | }, 685 | "source": [ 686 | "## 3. Random Forest" 687 | ] 688 | }, 689 | { 690 | "cell_type": "code", 691 | "execution_count": 0, 692 | "metadata": { 693 | "colab": { 694 | "autoexec": { 695 | "startup": false, 696 | "wait_interval": 0 697 | } 698 | }, 699 | "colab_type": "code", 700 | "collapsed": true, 701 | "id": "W-47YMYj3TNu" 702 | }, 703 | "outputs": [], 704 | "source": [ 705 | "models.append(\"random forest\")" 706 | ] 707 | }, 708 | { 709 | "cell_type": "code", 710 | "execution_count": 81, 711 | "metadata": { 712 | "colab": { 713 | "autoexec": { 714 | "startup": false, 715 | "wait_interval": 0 716 | }, 717 | "base_uri": "https://localhost:8080/", 718 | "height": 139, 719 | "output_extras": [ 720 | { 721 | "item_id": 1 722 | }, 723 | { 724 | "item_id": 2 725 | } 726 | ] 727 | }, 728 | "colab_type": "code", 729 | "executionInfo": { 730 | "elapsed": 22547, 731 | "status": "ok", 732 | "timestamp": 1519124671151, 733 | "user": { 734 | "displayName": "Pawan Bansal", 735 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg", 736 | "userId": "102337886470920224775" 737 | }, 738 | "user_tz": -330 739 | }, 740 | "id": "Zy__IZ1AwC-s", 741 | "outputId": "3e0e82aa-8f77-49d1-ec5b-83d533215db9" 742 | }, 743 | "outputs": [ 744 | { 745 | "name": "stderr", 746 | "output_type": "stream", 747 | "text": [ 748 | "[Parallel(n_jobs=-1)]: Done 10 out of 10 | elapsed: 21.9s finished\n" 749 | ] 750 | }, 751 | { 752 | "data": { 753 | "text/plain": [ 754 | "RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=None,\n", 755 | " max_features='auto', max_leaf_nodes=None,\n", 756 | " min_impurity_decrease=0.0, min_impurity_split=None,\n", 757 | " min_samples_leaf=1, min_samples_split=2,\n", 758 | " min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=-1,\n", 759 | " oob_score=False, random_state=7, verbose=1, warm_start=False)" 760 | ] 761 | }, 762 | "execution_count": 81, 763 | "metadata": { 764 | "tags": [] 765 | }, 766 | "output_type": "execute_result" 767 | } 768 | ], 769 | "source": [ 770 | "model = RandomForestRegressor(n_jobs=-1, n_estimators=10, verbose=1, random_state=seed)\n", 771 | "model.fit(X_train, y_train)" 772 | ] 773 | }, 774 | { 775 | "cell_type": "code", 776 | "execution_count": 82, 777 | "metadata": { 778 | "colab": { 779 | "autoexec": { 780 | "startup": false, 781 | "wait_interval": 0 782 | }, 783 | "base_uri": "https://localhost:8080/", 784 | "height": 86, 785 | "output_extras": [ 786 | { 787 | "item_id": 1 788 | }, 789 | { 790 | "item_id": 2 791 | } 792 | ] 793 | }, 794 | "colab_type": "code", 795 | "executionInfo": { 796 | "elapsed": 1335, 797 | "status": "ok", 798 | "timestamp": 1519124674034, 799 | "user": { 800 | "displayName": "Pawan Bansal", 801 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg", 802 | "userId": "102337886470920224775" 803 | }, 804 | "user_tz": -330 805 | }, 806 | "id": "liEZwYXY1E1o", 807 | "outputId": "7ea3b5d7-3d0b-4dbe-c1aa-b12019b639bd" 808 | }, 809 | "outputs": [ 810 | { 811 | "name": "stdout", 812 | "output_type": "stream", 813 | "text": [ 814 | "('training score: ', 0.9621975488319267)\n", 815 | "('test score: ', 0.7932394748872148)\n" 816 | ] 817 | }, 818 | { 819 | "name": "stderr", 820 | "output_type": "stream", 821 | "text": [ 822 | "[Parallel(n_jobs=2)]: Done 10 out of 10 | elapsed: 0.3s finished\n", 823 | "[Parallel(n_jobs=2)]: Done 10 out of 10 | elapsed: 0.0s finished\n" 824 | ] 825 | } 826 | ], 827 | "source": [ 828 | "training_score = model.score(X_train, y_train)\n", 829 | "test_score = model.score(X_test, y_test)\n", 830 | "\n", 831 | "print(\"training score: \", training_score)\n", 832 | "print(\"test score: \", test_score)" 833 | ] 834 | }, 835 | { 836 | "cell_type": "code", 837 | "execution_count": 0, 838 | "metadata": { 839 | "colab": { 840 | "autoexec": { 841 | "startup": false, 842 | "wait_interval": 0 843 | } 844 | }, 845 | "colab_type": "code", 846 | "collapsed": true, 847 | "id": "PESOXPwY27SO" 848 | }, 849 | "outputs": [], 850 | "source": [ 851 | "training_scores.append(training_score)\n", 852 | "test_scores.append(test_score)" 853 | ] 854 | }, 855 | { 856 | "cell_type": "markdown", 857 | "metadata": { 858 | "colab_type": "text", 859 | "id": "stPUH9TL4CYh" 860 | }, 861 | "source": [ 862 | "## 4. Neural Network" 863 | ] 864 | }, 865 | { 866 | "cell_type": "code", 867 | "execution_count": 0, 868 | "metadata": { 869 | "colab": { 870 | "autoexec": { 871 | "startup": false, 872 | "wait_interval": 0 873 | } 874 | }, 875 | "colab_type": "code", 876 | "collapsed": true, 877 | "id": "7ybHijZj5wRv" 878 | }, 879 | "outputs": [], 880 | "source": [ 881 | "models.append(\"neural network\")" 882 | ] 883 | }, 884 | { 885 | "cell_type": "code", 886 | "execution_count": 126, 887 | "metadata": { 888 | "colab": { 889 | "autoexec": { 890 | "startup": false, 891 | "wait_interval": 0 892 | }, 893 | "base_uri": "https://localhost:8080/", 894 | "height": 402, 895 | "output_extras": [ 896 | { 897 | "item_id": 107 898 | }, 899 | { 900 | "item_id": 191 901 | }, 902 | { 903 | "item_id": 300 904 | }, 905 | { 906 | "item_id": 416 907 | }, 908 | { 909 | "item_id": 492 910 | }, 911 | { 912 | "item_id": 598 913 | }, 914 | { 915 | "item_id": 599 916 | } 917 | ] 918 | }, 919 | "colab_type": "code", 920 | "executionInfo": { 921 | "elapsed": 224494, 922 | "status": "ok", 923 | "timestamp": 1519128490356, 924 | "user": { 925 | "displayName": "Pawan Bansal", 926 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg", 927 | "userId": "102337886470920224775" 928 | }, 929 | "user_tz": -330 930 | }, 931 | "id": "GOZfkMlQ4EtJ", 932 | "outputId": "1b0036ca-d929-4adb-d97a-b856e0dd84e4" 933 | }, 934 | "outputs": [ 935 | { 936 | "name": "stdout", 937 | "output_type": "stream", 938 | "text": [ 939 | "Epoch 1/10\n", 940 | "95503/95503 [==============================] - 23s 236us/step - loss: 1426592.9792\n", 941 | "Epoch 2/10\n", 942 | "80064/95503 [========================>.....] - ETA: 3s - loss: 1140652.504595503/95503 [==============================] - 22s 232us/step - loss: 2178143.3739\n", 943 | "Epoch 3/10\n", 944 | "95503/95503 [==============================] - 22s 234us/step - loss: 1195133.7699\n", 945 | "Epoch 4/10\n", 946 | "19328/95503 [=====>........................] - ETA: 17s - loss: 919646.060095503/95503 [==============================] - 22s 234us/step - loss: 999633.2443\n", 947 | "Epoch 5/10\n", 948 | "95503/95503 [==============================] - 22s 232us/step - loss: 862275.2634\n", 949 | "Epoch 6/10\n", 950 | " 3168/95503 [..............................] - ETA: 21s - loss: 466866.896795503/95503 [==============================] - 22s 231us/step - loss: 910655.6377\n", 951 | "Epoch 7/10\n", 952 | "93888/95503 [============================>.] - ETA: 0s - loss: 792743.879995503/95503 [==============================] - 22s 233us/step - loss: 802929.4407\n", 953 | "Epoch 8/10\n", 954 | "95503/95503 [==============================] - 22s 233us/step - loss: 856054.5725\n", 955 | "Epoch 9/10\n", 956 | "24096/95503 [======>.......................] - ETA: 16s - loss: 796268.264295503/95503 [==============================] - 23s 236us/step - loss: 854576.2596\n", 957 | "Epoch 10/10\n", 958 | "95503/95503 [==============================] - 22s 233us/step - loss: 716396.9110\n" 959 | ] 960 | }, 961 | { 962 | "data": { 963 | "text/plain": [ 964 | "" 965 | ] 966 | }, 967 | "execution_count": 126, 968 | "metadata": { 969 | "tags": [] 970 | }, 971 | "output_type": "execute_result" 972 | } 973 | ], 974 | "source": [ 975 | "def baseline_model():\n", 976 | " model = Sequential()\n", 977 | " model.add(Dense(100,input_dim=54, activation='relu', kernel_initializer='glorot_normal'))\n", 978 | " model.add(Dropout(0.2)) \n", 979 | " model.add(Dense(80, activation='relu', kernel_initializer='glorot_normal'))\n", 980 | " model.add(Dropout(0.2))\n", 981 | " model.add(Dense(60, activation='relu', kernel_initializer='glorot_normal'))\n", 982 | " model.add(Dropout(0.2)) \n", 983 | " model.add(Dense(40, activation='relu', kernel_initializer='glorot_normal'))\n", 984 | " model.add(Dropout(0.2))\n", 985 | " model.add(Dense(20, activation='relu', kernel_initializer='glorot_normal'))\n", 986 | " model.add(Dropout(0.2))\n", 987 | " model.add(Dense(10, activation='relu', kernel_initializer='glorot_normal'))\n", 988 | " model.add(Dropout(0.2))\n", 989 | " model.add(Dense(1, kernel_initializer='glorot_normal'))\n", 990 | " \n", 991 | " model.compile(loss='mean_squared_error', optimizer='adam')\n", 992 | " return model\n", 993 | "\n", 994 | "estimator = KerasRegressor(build_fn=baseline_model, nb_epoch=200, epochs=10, batch_size=32, verbose=True)\n", 995 | "# kfold = KFold(n_splits=10, random_state=seed)\n", 996 | "# results = cross_val_score(estimator, X_train.values, y_train.values, cv=kfold)\n", 997 | "# print(\"Results: %.2f (%.2f) MSE\" % (results.mean(), results.std()))\n", 998 | "\n", 999 | "estimator.fit(X_train, y_train)" 1000 | ] 1001 | }, 1002 | { 1003 | "cell_type": "code", 1004 | "execution_count": 127, 1005 | "metadata": { 1006 | "colab": { 1007 | "autoexec": { 1008 | "startup": false, 1009 | "wait_interval": 0 1010 | }, 1011 | "base_uri": "https://localhost:8080/", 1012 | "height": 86, 1013 | "output_extras": [ 1014 | { 1015 | "item_id": 11 1016 | } 1017 | ] 1018 | }, 1019 | "colab_type": "code", 1020 | "executionInfo": { 1021 | "elapsed": 5115, 1022 | "status": "ok", 1023 | "timestamp": 1519128546517, 1024 | "user": { 1025 | "displayName": "Pawan Bansal", 1026 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg", 1027 | "userId": "102337886470920224775" 1028 | }, 1029 | "user_tz": -330 1030 | }, 1031 | "id": "IyToCFgS5c7K", 1032 | "outputId": "5546c597-cb24-437a-fb1b-fdc31b46cfbe" 1033 | }, 1034 | "outputs": [ 1035 | { 1036 | "name": "stdout", 1037 | "output_type": "stream", 1038 | "text": [ 1039 | "95503/95503 [==============================] - 4s 43us/step\n", 1040 | "10612/10612 [==============================] - 0s 45us/step\n", 1041 | "('training score: ', 0.8259016551067639)\n", 1042 | "('test score: ', 0.7981640331110263)\n" 1043 | ] 1044 | } 1045 | ], 1046 | "source": [ 1047 | "train_pred = estimator.predict(X_train)\n", 1048 | "test_pred = estimator.predict(X_test)\n", 1049 | "\n", 1050 | "training_score = r2_score(y_train, train_pred)\n", 1051 | "test_score = r2_score(y_test, test_pred)\n", 1052 | "\n", 1053 | "print(\"training score: \", training_score)\n", 1054 | "print(\"test score: \", test_score)" 1055 | ] 1056 | }, 1057 | { 1058 | "cell_type": "code", 1059 | "execution_count": 0, 1060 | "metadata": { 1061 | "colab": { 1062 | "autoexec": { 1063 | "startup": false, 1064 | "wait_interval": 0 1065 | } 1066 | }, 1067 | "colab_type": "code", 1068 | "collapsed": true, 1069 | "id": "QN8YlA525tpE" 1070 | }, 1071 | "outputs": [], 1072 | "source": [ 1073 | "training_scores.append(training_score)\n", 1074 | "test_scores.append(test_score)" 1075 | ] 1076 | }, 1077 | { 1078 | "cell_type": "markdown", 1079 | "metadata": { 1080 | "colab_type": "text", 1081 | "id": "fNyX2xkpcmcx" 1082 | }, 1083 | "source": [ 1084 | "# Comparing all model's results" 1085 | ] 1086 | }, 1087 | { 1088 | "cell_type": "code", 1089 | "execution_count": 131, 1090 | "metadata": { 1091 | "colab": { 1092 | "autoexec": { 1093 | "startup": false, 1094 | "wait_interval": 0 1095 | }, 1096 | "base_uri": "https://localhost:8080/", 1097 | "height": 69, 1098 | "output_extras": [ 1099 | { 1100 | "item_id": 1 1101 | } 1102 | ] 1103 | }, 1104 | "colab_type": "code", 1105 | "executionInfo": { 1106 | "elapsed": 840, 1107 | "status": "ok", 1108 | "timestamp": 1519130258549, 1109 | "user": { 1110 | "displayName": "Pawan Bansal", 1111 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg", 1112 | "userId": "102337886470920224775" 1113 | }, 1114 | "user_tz": -330 1115 | }, 1116 | "id": "OTFvPxEeN4MY", 1117 | "outputId": "c2ed0976-4f05-41de-d0a7-a702ba8ad39d" 1118 | }, 1119 | "outputs": [ 1120 | { 1121 | "name": "stdout", 1122 | "output_type": "stream", 1123 | "text": [ 1124 | "['gradient boost', 'cat boost', 'random forest', 'neural network']\n", 1125 | "[0.7936297533635706, 0.7936297533635706, 0.9621975488319267, 0.8259016551067639]\n", 1126 | "[0.7696216055989064, 0.827240593918934, 0.7932394748872148, 0.7981640331110263]\n" 1127 | ] 1128 | } 1129 | ], 1130 | "source": [ 1131 | "print(models)\n", 1132 | "print(training_scores)\n", 1133 | "print(test_scores)" 1134 | ] 1135 | }, 1136 | { 1137 | "cell_type": "code", 1138 | "execution_count": 224, 1139 | "metadata": { 1140 | "colab": { 1141 | "autoexec": { 1142 | "startup": false, 1143 | "wait_interval": 0 1144 | }, 1145 | "base_uri": "https://localhost:8080/", 1146 | "height": 522, 1147 | "output_extras": [ 1148 | { 1149 | "item_id": 1 1150 | } 1151 | ] 1152 | }, 1153 | "colab_type": "code", 1154 | "executionInfo": { 1155 | "elapsed": 924, 1156 | "status": "ok", 1157 | "timestamp": 1519134063364, 1158 | "user": { 1159 | "displayName": "Pawan Bansal", 1160 | "photoUrl": "//lh4.googleusercontent.com/-hQniqzw3AW0/AAAAAAAAAAI/AAAAAAAAAGs/dTfAX9OOw5w/s50-c-k-no/photo.jpg", 1161 | "userId": "102337886470920224775" 1162 | }, 1163 | "user_tz": -330 1164 | }, 1165 | "id": "1Sue-rrkOnFc", 1166 | "outputId": "ee20a996-e6ef-4db8-fbfd-6bd6f0afbab3" 1167 | }, 1168 | "outputs": [ 1169 | { 1170 | "data": { 1171 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlUAAAH5CAYAAACoMMu6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4yLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvNQv5yAAAIABJREFUeJzs3Xt8zvXj//GnjU2W4wjNWg7tQjNm\nm400LDk2WeSwGUVKxTp8nFbER0V8wmfIIdEHn4ys5ZeUckwqZCgy5FA2otYUbbXNdv3+8N316Wpn\nXjtYj/vt5nbj/X5dr/frdV2vzfN6vV/v97uS1Wq1CgAAANfFoawbAAAAUBEQqgAAAAwgVAEAABhA\nqAIAADCAUAUAAGAAoQoAAMAAQhWAUrd7924NGDBAPj4+slgsiouLK3YdSUlJslgsmj9/foHbJOn3\n33/XSy+9pM6dO6tFixYKDg627XvrrbfUo0cPeXl5yWKxKCkp6do7hiKLiIiw+xyKa+LEibJYLAZb\nBFy/ymXdAMCkPXv2aOjQoXbbqlWrpttvv13333+/hgwZosqV/zfsrVar3nvvPe3YsUOHDx/Wjz/+\nqNq1a6t58+Z6/PHH1bp169LuQoX366+/asyYMWrQoIEmTpyoqlWrqm3btiV6zKVLl2rVqlUaPny4\nLBaLbr75ZklXw920adN0zz33aOTIkapcubLq1KlTom0xZc+ePdq7d6+GDRumGjVqlHVzAIhQhQrq\nvvvuU1BQkKxWq5KTk/X//t//04wZM3Ty5Em9+OKLtnIZGRkaP368WrRooV69eqlRo0b66aeftGbN\nGg0cOFAzZ87U/fffX4Y9qXgOHTqkS5cu6eWXX1a3bt2M1u3m5qavv/5ajo6Odts///xzeXp6asKE\nCbm2S9L06dNVq1Yto20paXv37tWCBQsUGhpKqALKCUIVKqSWLVvahaGwsDD17NlT69at0zPPPGOb\njXB0dNSqVavUrl07u9cPGDBAvXv31syZMxUSEiIHhxvnTHlWVpYyMjJ00003lXVT8pScnCxJqlmz\npvG6K1WqJGdn51zbf/rpJ9166615bpdkPFBlZmYqOzs7z7YAqLhunP8pgOtQrVo1tW7dWlarVWfO\nnLFtr1y5cq5AJUl169ZVu3bt9PPPP+vnn38utP4ffvhBUVFR6tKli7y8vNS+fXsNGjRI7777rl05\nq9Wqt99+Ww8++KB8fHzk4+OjkJAQRUdH25VLSUnRP//5T3Xq1EleXl7q1KmT/vnPf+rixYt25eLi\n4mSxWPT555/rtddeU9euXeXt7a0PP/zQVubQoUN68sknFRAQIC8vL3Xv3l2LFi3SlStX7Or69ttv\nFRkZqbvvvlteXl666667FBERoR07dhTaf0k6evSo7TitWrVSr169tHTpUmVlZdnKBAcH22aLhg4d\nKovFUqR1Mfv27dOgQYPk7e2tDh06aNq0aUpLS8tV7q9rqnLen6SkJO3du9d2vJz1ODlruXK2R0RE\n2Or68ccfNWXKFHXu3FleXl7q2LGjJk+enGs8zJ8/XxaLRd9++61mzJihoKAgeXt76+DBg7Yyn3/+\nuYYPHy4/Pz+1atVKISEhiomJydX+4OBgRURE6OTJk3r00Ufl4+MjX19fRUZG2gKgdHU90YIFCyRJ\n99xzj639f11L9lc565iSkpL05JNPys/PT/7+/po4caJSU1OVnZ2txYsXKzg4WK1atVJoaKji4+Nz\n1ZOWlqbZs2era9eutrEyfvx4nT17NlfZX3/9VZMmTVJAQIDatGmjiIgIHT58ON82FnW85qWoP4dA\nSWGmCn8biYmJkoo+Q3L+/HlVqVKl0FMrV65c0cMPP6wLFy4oLCxMt99+u3777TcdO3ZM+/btU2ho\nqK3suHHjtGHDBrVu3VqjRo1S9erVderUKX300Ud66qmnJEmXL1/W4MGD9f3336tfv35q2bKlEhIS\nFBMTo927d2vdunW2NUE5Zs6cqStXrmjAgAFycXFR48aNJUk7duzQ6NGj5eHhoeHDh6tmzZo6ePCg\n5s2bp4SEBM2bN0+SdPHiRQ0bNkySNGjQIN166626ePGiDh8+rK+++kqdO3cu8D04dOiQIiIiVLly\nZYWHh6tu3bravn27Xn31VR09elSzZ8+WJD333HPauXOn1q5dq1GjRqlJkyaFfg5fffWVHn74Ybm4\nuGjkyJGqXr26Pvjgg1yn8vLi7++vWbNmacaMGapdu7ZGjRol6WqIat++vd5++23t27dPs2bNknQ1\nTEvSuXPnNHDgQGVmZqp///667bbb9P333ysmJkZ79uzRO++8o+rVq9sda+zYsapataqGDx8uSapX\nr54kae3atZoyZYratGmjUaNG6aabbtLnn3+uqVOn6syZM7n6ceHCBQ0dOlRdu3bV+PHjdfToUa1d\nu1a//fabli9fLkkaOHCgfvvtN23evFlRUVGqXbu2rV+FSUtL07Bhw9SuXTv94x//0KFDh/TOO+8o\nPT1dtWrV0ldffaWIiAhlZmZq+fLlevzxx7Vt2zbbmMvMzNSIESO0f/9+de/eXQ8//LDtvfnss8/0\nzjvvqEGDBnZlDx06pPvvv1+tW7fW0aNH9fDDD+c5O1jU8ZqX4vwcAiXGClQgu3fvtnp6elrnz59v\n/fnnn60///yz9ejRo9apU6daPT09rf379y9SPTt27LB6enpax40bV2jZhIQEq6enp/X1118vsNzG\njRutnp6e1rFjx1qzsrLs9v3533PmzLF6enpa//vf/9qV+e9//2v19PS0zp0717btnXfesXp6elq7\ndetmTUtLsyv/xx9/WDt06GANCwuzZmZm2u178803rZ6entbdu3dbrVardcuWLVZPT0/rxo0bC+1v\nXgYOHGht0aKFNSEhwbYtOzvbGhkZafX09LR+/vnnudqcc+yi1H3nnXdaT506ZduWnp5u7devn9XT\n09M6b9482/bExMRc26xWq7VLly7WIUOG5Kp7woQJVk9Pz1zbR40aZQ0MDLT+8MMPdtu//vpra4sW\nLezqnzdvntXT09M6ZMiQXO/zhQsXrF5eXtZnn3021zFefPFFa/Pmza1nzpyxa2den0PO+D158mSu\n4yYmJuaqOz9Dhgyxenp6WpcuXWq3/cknn7RaLBZraGioNSMjw7Y9Z1zExMTYtq1du9bq6elpnTlz\npl0d27dvt43vHGvWrLF6enpao6Oj7crmjL8uXbrYthVnvFqtuT+7ov4cAiWJ03+okObPn6/27dur\nffv26tOnj1avXq1u3bpp4cKFhb72u+++0/jx41W/fn1NnDix0PI5MxZ79uwp8FThhg0bJEkTJkzI\ntUbrz//evHmz6tSpo4EDB9qVGThwoOrUqaMtW7bkqnvw4MG51lB99tlnSk5O1gMPPKBLly4pJSXF\n9icoKMhW5s99+PTTT/Xbb78V2uc/+/nnn3XgwAEFBwerefPmtu2VKlXS448/buvTtfhz3Tmzb5Lk\n5OSkhx566JrqLMzly5e1Y8cOBQcHy8nJye59c3Nz02233WZ73/5s2LBhdleWStJHH32kjIwM9e/f\n366elJQUBQcHKzs727ZYPsctt9yiXr162W0LDAyUJH3//ffX3T9HR0e705yS5OfnJ6vVqsGDB6tK\nlSp22/963M2bN8vBwUGPPfaYXR05t6vYunWrsrOzJUlbtmyRo6OjbfYuR1hYWK7Z1uKM17wU9ecQ\nKEmc/kOFNHDgQPXo0UOZmZk6fvy43njjDZ0/f77QhcOJiYm2/6yXLl1apMvr3dzcNGrUKL3++uvq\n2LGjWrRoocDAQPXo0UPe3t62ct9//73q1atnO8WUn6SkJHl5eeX6D7py5cq6/fbbdeTIkVyv+XPg\nyHHy5ElJV0+55Sdn0Xi7du3Ut29fxcXFacOGDfLy8lKHDh3Uq1cvNWvWrND2SsqzXJMmTeTg4GA7\n9VpcOa/L6zRhYe26VqdPn1Z2drZiY2MVGxubZxl3d/dc226//fZc23I+g4ICYM5nUFDdOafKfvnl\nl3zrKap69erl+jnIOcXdqFEju+05p8r/fNykpCTdcssteZ5Gb9asmRISEnTx4kW5uroqMTFR9erV\nyxWgnJyc5O7urkuXLtm2FWe85qWoP4dASSJUoULy8PBQhw4dJEmdOnWSr6+vwsLCNGXKFM2dOzfP\n1yQlJWnYsGFKS0vTf/7zn2LdWPCZZ55R//79tWPHDu3bt0+xsbFatmyZHnnkEY0bN85InwpStWrV\nXNusVqsk2W4ZkZdbbrnF9veZM2dqxIgR2rlzp/bt26c333xTixcv1nPPPachQ4aUTMPLoZz3rU+f\nPvmuw8krnBf0GcycOdPuvf6zv4aov94OIq/6rkdB9ed3lauJ4xamuOM1L2X9cwgQqvC30LZtW91/\n//1av369IiIict1sMikpSUOHDtXly5f15ptvqmXLlsU+hru7uyIiIhQREaH09HSNGDFCb7zxhoYP\nHy5XV1fdfvvt2rp1q5KTkwucrXJ3d9fp06d15coVu9mqK1eu6LvvvstzJiMvOTMnN910ky1gFsbT\n01Oenp565JFHdOnSJT344IOaPXu2wsPDValSpTxfkzO7ceLEiVz7Tp06pezs7CK3Ob+6T506lWtf\nXscz4bbbblOlSpWUmZlZ5PctPzmfQe3ata+7rr/K7/Moae7u7vr000916dKlXBdxnDx5UjfffLNt\n4by7u7s+++wz/fbbb3azVRkZGUpMTLSb7bqW8Zpf+wr6OQRKEmuq8LfxxBNPyNHRMdcVRGfPntXQ\noUN16dIlLVu2TF5eXsWq9/Lly8rMzLTb5uzsbDtl9euvv0qSQkJCJEn/+te/bGtOcvx5JqBr165K\nSUnRunXr7Mq8/fbbSklJUdeuXYvUro4dO8rV1VVLly7N87TRH3/8YVs/9csvv+RqU40aNdSoUSP9\n/vvvSk9Pz/c4rq6u8vHx0fbt23X8+HG7Pr3++uuSpHvvvbdIbf6runXrqk2bNtq2bZtOnz5t256R\nkaH//Oc/11RnYWrXrq1OnTpp8+bNdrdFyGG1WpWSklKkunr27CknJyfNnz9ff/zxR679ly9fVkZG\nxjW1s1q1apL+N75KS9euXZWdnW37bHN88sknOnLkiIKDg20zXvfcc4+ysrJsVy3mWL16da61e8UZ\nr3kp6s8hUJKYqcLfhoeHh3r16qUNGzZo37598vPz02+//aahQ4fq7NmzioiI0OnTp+3+85aku+66\nq8CZpT179mjy5Mnq1q2bGjduLBcXFx0+fFixsbFq3bq17Zd6z5499fHHH2v9+vX6/vvvFRwcrBo1\naui7777Trl279P7770uSHnnkEW3atEnTpk3TkSNH1KJFCyUkJCg2NlaNGzfWI488UqT+VqtWTTNn\nztSTTz6pHj16qF+/fvLw8NClS5d06tQpbd68WQsWLFBAQIDWr1+vFStWqGvXrvLw8FDlypX15Zdf\nateuXerZs2eep7b+7Pnnn1dERITCw8MVFhamevXqafv27dq1a5fuu+8+tW/fvkhtzsvEiRMVERGh\nwYMHKzw83HZLhT/f/8q0qVOnKiwsTEOGDNH999+vli1bKjs7W4mJidq6dav69u2rMWPGFFpPgwYN\nNHXqVE2aNEm9evVSnz595ObmppSUFB0/flxbtmzRxo0bc61lKoqcRyi9+uqrCgkJkbOzs+644w55\nenoWu67iCA0N1bvvvqulS5fq7Nmz8vPz05kzZ7R69WrVrVtXzz77rK3sAw88oLfffluvvfaakpKS\n1KZNGyUkJGjTpk267bbb7D7D4ozXvBT15xAoSYQq/K08/vjj2rhxo6Kjo7Vq1Sr98ssvtoXWq1at\nyvM1K1euLDBUWSwW3Xvvvdq7d682bNig7OxsNWzYUI899liuq55mz54tPz8/xcbG6rXXXpODg4Ma\nNWqkHj162MpUr15dMTExmjdvnrZt26a4uDi5urpq0KBBGjNmTK5FvwW5++67FRsbq9dff13vvfee\nLl68qBo1aui2227TQw89ZFs3FhAQoISEBO3YsUM//fSTrV0TJkwo0nqqVq1aac2aNZo3b55iYmKU\n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\nzVJJ0j333COLxaI9e/bkOnZSUpJGjBghf39/eXt7q3v37po3b55t/8GDBzV8+HAFBgbKx8dHAwYM\nsB3/6NGjGjFihAICAhQYGKhRo0bp1KlTdv2yWCxatGiRevfuLW9vb0nSxYsX9cILLyg4OFg+Pj4a\nNGiQ9u3bZ/ItzRen/wAAqMAeeOABLV++XKmpqerevbvq16+vZs2a6dNPP9UTTzyh2rVr695779X3\n33+vN998U7/++qtmzJih5cuX66OPPlKzZs3k5+enc+fO6cCBA5KuhrOVK1fa6r/55pvVoEGDXMf+\n97//rV27dumuu+5So0aNdObMGX311VeSpOPHjysiIkIZGRny8/OTh4eHvvzyS2VmZury5cuKiIjQ\npUuX1LlzZ2VmZmr79u06fPiwNm7cqJo1a9qOMX/+fHXv3l1NmzZVdna2nnjiCe3fv19+fn4KDAzU\npk2bNHz4cK1fv15NmjQp0feaUAUAQAU2evRoxcXFKTU1VeHh4bY1VY8++qgkqWXLlqpRo4aaN2+u\nAwcO6N1339ULL7ygK1euSJKaNWumfv36qWnTpqpataok6fnnn7eFqieffDLfNVU5dQQEBOjuu+9W\n06ZNVbny1eixZs0aZWRkKDg4WIsWLZIkZWVlqVKlSlq7dq0uXbqkdu3aacmSJZKkvn37KiEhQZs2\nbdLAgQNtx3jsscf01FNPSZK+/vpr7d+/Xy4uLmrZsqUkycPDQ0eOHFFcXJzGjh1r6F3NG6EKAIC/\noZxTgp999pk+++wz23ar1arExEQNGzZMR48e1ebNm7Vp0yY5OjqqZ8+e+te//iUHh6KtHhozZozO\nnz+v6OhozZkzR05OThoyZIgmTJigpKQkSVKbNm1s5R0dHe3a1rRpU9u+Jk2aKCEhQefOnbM7Rtu2\nbXP1KTU11Rb6cpw5c6ZIbb4ehCoAACq4nBCUnZ1t2+bm5qYTJ07o+eef19ChQ23bExMT5e7uroyM\nDC1btky7d+9WrVq1NH78eL3//vsaPHiw/Pz85ODgoOzsbFmt1nyP6+7urjVr1igtLU0nTpzQE088\noeXLl2vo0KG22a2c04E57atUqZLc3NwkyW4N1enTpyVJt956q90xnJyc7PokSfXq1dO2bdts+/74\n4w9dvny5GO/YtSFUAQBQwTVs2FCJiYmaN2+etm3bpuHDhys8PFyffPKJXn31VR08eFDOzs46duyY\n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\ngYGB+uCDD4w2FgAAoLwqdKbqr6xWa57bMzIyJEn16tXT008/rZdeeklRUVEKCgrSzTffXGCd8fHx\nxW1GsaSnpZZo/cWVnZ11TfvSylE/SvozK2uMGfMYM6WnoDFR2H7GTOmpCGOmPI0XqezHTKGhqlGj\nRpKk8+fPS5IuXLggSXJ3d1d6erocHBxUpUoVW7mePXuqW7du2rRpkzZu3Kgff/yx0FDl6+t7XZ0o\nzMG31pZo/cXl4OCY5/bs7Kx890lStWouJdWkYvP1bV7WTShRjBnzGDOlp6AxwZgpPyrCmClP40Uq\nnTFTUHAr9PRfUFCQXF1dFRMTo9WrVys2NlZubm5yc3OTt7e3Ro8eLUnq1auXnJycFBcXp7fffltf\nfPGF6tevr9tuu81cTwAAAMqpQkOVs7OzoqOj5eLiounTp8vV1VXR0dFycLB/af369TV79mylpKTo\n5ZdfloeHhxYtWqTKlYt9hhEAAOCGU6TE4+/vrw0bNuTafuzYMbt/d+vWTd26dTPTMgAAgBsId1QH\nAAAwgFAFAABgAKEKAADAAEIVAACAAYQqAAAAAwhVAAAABhCqAAAADCBUAQAAGECoAgAAMIBQBQAA\nYAChCgAAwABCFQAAgAGEKgAAAAMIVQAAAAYQqgAAAAwgVAEAABhAqAIAADCAUAUAAGAAoQoAAMAA\nQhUAAIABhCoAAAADCFUAAAAGEKoAAAAMIFQBAAAYQKgCAAAwgFAFAABgAKEKAADAAEIVAACAAYQq\nAAAAAwhVAAAABhCqAAAADCBUAQAAGECoAgAAMIBQBQAAYAChCgAAwABCFQAAgAGEKgAAAAMIVQAA\nAAYQqgAAAAwgVAEAABhAqAIAADCAUAUAAGAAoQoAAMAAQhUAAIABhCoAAAADCFUAAAAGEKoAAAAM\nIFQBAAAYQKgCAAAwgFAFAABgAKEKAADAAEIVAACAAYQqAAAAAwhVAAAABhCqAAAADCBUAQAAGECo\nAgAAMIBQBQAAYAChCgAAwABCFQAAgAGEKgAAAAMIVQAAAAYQqgAAAAwgVAEAABhAqAIAADCAUAUA\nAGAAoQoAAMAAQhUAAIABhCoAAAADCFUAAAAGEKoAAAAMIFQBAAAYQKgCAAAwgFAFAABgAKEKAADA\nAEIVAACAAYQqAAAAA4oUquLj4xUSEiIvLy+Fhobqm2++ybfsyZMn1apVK1ksFm3atMlYQwEAAMqz\n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\nAz799FO2b99O+/bta+z3dVWXLl2YMmUKenp6XLx4kVu3bpGXl1fteXwZr9r3aqKrX6rHt0OHDnHo\n0CEA7t69i76+vs5xrHv37qSnp5OVlYWZmRmVlZWcPn2aS5cuMWDAAODZIwetW7fG398fgISEBNLT\n07ViWbhwIR06dKiyzc7OjrCwsCrfn/ku1Iuk6mUYGBhgaGgIPEt8YmNj6dmzJxMmTGDnzp2kpaXx\n9OnTKn/3d1ONDRs2JCoqCn19feDZcwfPa9asmaacet/LZtrq99YVg7oOXXXp2hceHk5ycjIXL15k\n8+bNbN++nfT09Hee9dc1UVFR5OXl4evrS6dOnZgyZQpPnjwBpN3rmlatWml+37FjB9nZ2ZpbMoGB\ngTx8qL1m2vNjAWg/2/m6bf7BBx8AoFAoAGjatKnmg+fFsagmNb2HiYlJlQ+zb775RpOgwbOZr9at\nW2NlZUVmZiYpKSlERUWRmJhY7/uaut11fUboOo8nT54E/t8/dN3GfdW+9zLx6eqX4eHhGBsba+Ju\n3Lixzva0s7MjKSmJvXv30rVrVyorK9m5cycqlYoePXq8dCzPH5eakZERFy9e5Nq1a1hbW790Xf+U\nd5/WvQXqK+3t27ezd+9eranrmjx+/JgbN25w9uxZnXXt27dP5xS6mrOzM2VlZcTGxnL79m2OHz+u\nNWtVHfVAmJ6errkK0CU1NZVdu3YRGRkJgL29PT179kShULBlyxb279/P1q1bUSgUODk50bdvXwCW\nLVvGjh07SElJwczMDHNzc1auXElxcTEdOnTA2NiY+/fvU1ZWpoklKSmpyn1sUT1nZ2fg2bnev38/\nq1atIj8/X7O/pKSE5ORkrZlQafe6788//+T06dNVno2qjnq8iYyMZNeuXaSmpmr21dTmtcXCwgIz\nMzNSUlLYsWOH5p9w1H3qReqYjhw5wq1bt/jll19YuXIlKpWKPXv2kJ2dTdu2bWnbti0VFRUUFxdr\n+tqZM2dITEyktLS01uL/r6rpPKrX2U1LS2P//v1aM1k1edW+VxP1+BYbG0thYSGZmZlERkby/vvv\n6xzH1InT8ePH6dq1K127dtUkh3Z2dgD069ePoqIiVqxYwYoVKygqKqq2nz1v7dq16OvrM2nSpFo5\ntjdVL5KqDh064O/vz927d9mzZ49mEWd147+oV69euLi4cPnyZRITEzXPl6jrmjdvHnfv3mXnzp3Y\n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\nAABJRU5ErkJggg==\n", 1172 | "text/plain": [ 1173 | "" 1174 | ] 1175 | }, 1176 | "metadata": { 1177 | "tags": [] 1178 | }, 1179 | "output_type": "display_data" 1180 | } 1181 | ], 1182 | "source": [ 1183 | "SMALL_SIZE = 8\n", 1184 | "MEDIUM_SIZE = 10\n", 1185 | "BIGGER_SIZE = 12\n", 1186 | "\n", 1187 | "mpl.rc('font', size=MEDIUM_SIZE) # controls default text sizes\n", 1188 | "mpl.rc('axes', titlesize=18) # fontsize of the axes title\n", 1189 | "mpl.rc('axes', labelsize=16) # fontsize of the x and y labels\n", 1190 | "mpl.rc('xtick', labelsize=MEDIUM_SIZE) # fontsize of the tick labels\n", 1191 | "mpl.rc('ytick', labelsize=MEDIUM_SIZE) # fontsize of the tick labels\n", 1192 | "mpl.rc('legend', fontsize=BIGGER_SIZE) # legend fontsize\n", 1193 | "mpl.rc('figure', titlesize=BIGGER_SIZE) # fontsize of the figure title\n", 1194 | "\n", 1195 | "y_pos = np.arange(len(models))\n", 1196 | "rects1 = plt.bar(y_pos-0.12, training_scores, 0.35, alpha=0.8, color=color[2], label=\"train score\")\n", 1197 | "rects2 = plt.bar(y_pos+0.13, test_scores, 0.35, alpha=0.8, color=color[5], label=\"test score\")\n", 1198 | "plt.xticks(y_pos, models)\n", 1199 | "plt.xlabel('Models')\n", 1200 | "plt.title('R2 scores of different models')\n", 1201 | "plt.legend()\n", 1202 | "\n", 1203 | "def autolabel(rects):\n", 1204 | " \"\"\"\n", 1205 | " Attach a text label above each bar displaying its height\n", 1206 | " \"\"\"\n", 1207 | " for rect in rects:\n", 1208 | " height = rect.get_height()\n", 1209 | " plt.text(rect.get_x() + rect.get_width()/2., 1.01*height,\n", 1210 | " '%.2f' % float(height),\n", 1211 | " ha='center', va='bottom')\n", 1212 | "\n", 1213 | "autolabel(rects1)\n", 1214 | "autolabel(rects2)\n", 1215 | "\n", 1216 | "plt.show()" 1217 | ] 1218 | } 1219 | ], 1220 | "metadata": { 1221 | "accelerator": "GPU", 1222 | "colab": { 1223 | "default_view": {}, 1224 | "name": "Untitled0.ipynb", 1225 | "provenance": [], 1226 | "version": "0.3.2", 1227 | "views": {} 1228 | }, 1229 | "kernelspec": { 1230 | "display_name": "Python 3", 1231 | "language": "python", 1232 | "name": "python3" 1233 | }, 1234 | "language_info": { 1235 | "codemirror_mode": { 1236 | "name": "ipython", 1237 | "version": 3 1238 | }, 1239 | "file_extension": ".py", 1240 | "mimetype": "text/x-python", 1241 | "name": "python", 1242 | "nbconvert_exporter": "python", 1243 | "pygments_lexer": "ipython3", 1244 | "version": "3.6.4" 1245 | } 1246 | }, 1247 | "nbformat": 4, 1248 | "nbformat_minor": 1 1249 | } 1250 | -------------------------------------------------------------------------------- /scripts/bash/git_star_pred_DO_conf cmds: -------------------------------------------------------------------------------- 1 | git clone https://github.com/Doodies/Github-Stars-Predictor.git 2 | cd Github-Stars-Predictor/scripts/bash 3 | vim settingUpDOServer.sh 4 | 5 | chmod +x settingUpDOServer.sh 6 | ./settingUpDOServer.sh 7 | 8 | cd ./../nodejs/ 9 | tmux new -s dataset 10 | node githubGraphQLApiCallsDO_V3.js 11 | -------------------------------------------------------------------------------- /scripts/bash/settingUpDOServer.sh: -------------------------------------------------------------------------------- 1 | cd ./../nodejs 2 | curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - 3 | sudo apt-get install -y nodejs 4 | npm install 5 | echo "TOKEN = 6 | START = 0 7 | END = 10000" > .env 8 | mkdir graphQlData 9 | cd ./../../ 10 | cp .tmux.conf ~/.tmux.conf 11 | -------------------------------------------------------------------------------- /scripts/nodejs/getting_repos_v2.js: -------------------------------------------------------------------------------- 1 | const request = require('request'); 2 | let url = 'https://api.github.com/search/repositories'; 3 | const json2csv = require('json2csv'); 4 | const fs = require('fs'); 5 | const dateFormat = require('dateformat'); 6 | const dotenv = require("dotenv"); 7 | dotenv.config(); 8 | dotenv.load(); 9 | 10 | let data = [], countExceeds = 0; 11 | let fD = new Date(); 12 | let startTime = new Date(); 13 | let nReq = 0, nRes = 0, setI, reqSetI; 14 | 15 | function getRepos() { 16 | if (fD <= new Date("2008-1-1")) { 17 | clearInterval(reqSetI); 18 | console.log("Task completed"); 19 | // saving data 20 | setI = setInterval(() => { 21 | if (nRes === nReq) { 22 | console.log("total requests: " + nReq + "\ttotal responses: " + nRes + "\texceed count: " + countExceeds); 23 | return saveData(); 24 | } 25 | }, 10 * 1000); 26 | return; 27 | } 28 | nReq++; 29 | let myDate; 30 | myDate = fD = new Date(fD - 1000 * 60 * 60 * 24); 31 | let options = { 32 | method: 'GET', 33 | url: url, 34 | qs: { 35 | q: "stars:>=100 created:" + dateFormat(myDate, "yyyy-mm-dd"), 36 | sort: "stars", 37 | order: "asc", 38 | page: 1, 39 | per_page: 101, 40 | client_id: process.env.CLIENT_ID, 41 | client_secret: process.env.CLIENT_SECRET 42 | }, 43 | headers: {"User-Agent": "hackbansu"} 44 | }; 45 | request(options, (err, res, body) => { 46 | // error handling 47 | if (err || !body) { 48 | console.log("body ==> ", body); 49 | console.log("error ==> ", err); 50 | console.log("some error occurred"); 51 | clearInterval(reqSetI); 52 | return saveData(); 53 | } 54 | body = JSON.parse(body); 55 | if (!body.items) { 56 | console.log("body ==> ", body); 57 | console.log("body.items not found"); 58 | clearInterval(reqSetI); 59 | return saveData(); 60 | } 61 | 62 | // this request work 63 | let modItems = body.items.map(x => { 64 | return { 65 | "RepoName": x.name, 66 | "ownerName": x.owner["login"], 67 | "Type": x.owner.type, 68 | "SideAdmin": x.owner["site_admin"], 69 | }; 70 | }); 71 | data = data.concat(modItems); 72 | nRes++; 73 | console.log(dateFormat(myDate, "dd-mm-yyyy") + "\tResults: " + body["total_count"] + "\tresNum: " + nRes 74 | + "\tcompleted at: " + (new Date() - startTime) / 1000.0 + "s" + "\trepos fetched: " + data.length); 75 | if (body["total_count"] > 100) { 76 | countExceeds++; 77 | console.log("************ count exceeded *************"); 78 | } 79 | }) 80 | } 81 | 82 | reqSetI = setInterval(getRepos, 2050); 83 | 84 | function saveData() { 85 | clearInterval(setI); 86 | let fields = ['RepoName', 'ownerName', 'Type', 'SideAdmin']; 87 | console.log("len: ", data.length); 88 | let csv = json2csv({data: data, fields: fields}); 89 | fs.writeFile('./repos/file_2014-01-01_2018-02-15.csv', csv, function (err) { 90 | if (err) throw err; 91 | console.log('file saved'); 92 | }); 93 | } -------------------------------------------------------------------------------- /scripts/nodejs/githubGraphQLApiCallsDO_V2.js: -------------------------------------------------------------------------------- 1 | //setInterval based implementation 2 | 3 | const fs = require('fs'); 4 | const csv = require('csvtojson'); 5 | const jsonfile = require("jsonfile"); 6 | const dotenv = require("dotenv"); 7 | dotenv.config(); 8 | dotenv.load(); 9 | const {request, GraphQLClient} = require('graphql-request'); 10 | let url = "https://api.github.com/graphql"; 11 | const client = new GraphQLClient(url, { 12 | headers: { 13 | Authorization: 'bearer ' + process.env.TOKEN, 14 | }, 15 | }); 16 | 17 | // get query for data 18 | function getQuery() { 19 | let q = 'query ($owner: String!, $name: String!, $isUser:Boolean!) { \n' + 20 | ' \n' + 21 | ' organization(login: $owner) @skip(if: $isUser){\n' + 22 | ' login\n' + 23 | ' \n' + 24 | ' repositories{\n' + 25 | ' totalCount\n' + 26 | ' } \n' + 27 | ' \n' + 28 | ' location\t\t#location of organization\n' + 29 | ' \n' + 30 | ' members{\n' + 31 | ' totalCount\n' + 32 | ' }\n' + 33 | ' \n' + 34 | ' websiteUrl \n' + 35 | ' }\n' + 36 | ' \n' + 37 | ' user(login: $owner) @include(if: $isUser){ \n' + 38 | ' login\n' + 39 | ' \n' + 40 | ' followers{\t\t# number of followers of the user\n' + 41 | ' totalCount\n' + 42 | ' } \n' + 43 | '\trepositories{\t\t# number of repositories of the user\n' + 44 | ' totalCount\n' + 45 | ' }\n' + 46 | ' \n' + 47 | ' following{\t# following\n' + 48 | ' totalCount\n' + 49 | ' }\n' + 50 | ' \n' + 51 | ' location # location of user\n' + 52 | ' \n' + 53 | ' organizations{\n' + 54 | ' totalCount\n' + 55 | ' }\n' + 56 | ' \n' + 57 | ' gists(last:100){\n' + 58 | ' edges{\n' + 59 | ' node{ \n' + 60 | ' comments{\n' + 61 | ' totalCount\n' + 62 | ' }\n' + 63 | ' stargazers{\n' + 64 | ' totalCount\n' + 65 | ' } \n' + 66 | ' }\n' + 67 | ' }\n' + 68 | ' totalCount\n' + 69 | ' } \n' + 70 | ' \n' + 71 | ' websiteUrl\n' + 72 | ' }\n' + 73 | ' \n' + 74 | ' repository(owner: $owner, name: $name) {\n' + 75 | ' name\t\t# name of the repo \n' + 76 | '\n' + 77 | ' primaryLanguage{\n' + 78 | ' name\n' + 79 | ' }\n' + 80 | '\n' + 81 | ' license\n' + 82 | ' \n' + 83 | ' isArchived\n' + 84 | '\n' + 85 | ' hasWikiEnabled\n' + 86 | ' \n' + 87 | ' forkCount\n' + 88 | ' \n' + 89 | ' # readme.md of the repo\n' + 90 | ' readme_md:object(expression: "master:README.md"){\n' + 91 | ' ... on Blob{\n' + 92 | ' text\n' + 93 | ' byteSize\n' + 94 | ' }\n' + 95 | ' }\n' + 96 | ' readme_txt:object(expression: "master:README.txt"){\n' + 97 | ' ... on Blob{\n' + 98 | ' text\n' + 99 | ' byteSize\n' + 100 | ' }\n' + 101 | ' }\n' + 102 | ' readme_markdown:object(expression: "master:README.markdown"){\n' + 103 | ' ... on Blob{\n' + 104 | ' text\n' + 105 | ' byteSize\n' + 106 | ' }\n' + 107 | ' }\n' + 108 | ' readme_tst:object(expression: "master:README.tst"){\n' + 109 | ' ... on Blob{\n' + 110 | ' text\n' + 111 | ' byteSize\n' + 112 | ' }\n' + 113 | ' }\n' + 114 | ' readme_:object(expression: "master:README"){\n' + 115 | ' ... on Blob{\n' + 116 | ' text\n' + 117 | ' byteSize\n' + 118 | ' }\n' + 119 | ' }\n' + 120 | ' \n' + 121 | ' stars: stargazers{\n' + 122 | ' totalCount\n' + 123 | ' }\n' + 124 | ' createdAt\n' + 125 | ' updatedAt\n' + 126 | ' pushedAt\n' + 127 | '\n' + 128 | ' \n' + 129 | ' description\n' + 130 | ' \n' + 131 | ' subscribersCount: watchers{\n' + 132 | ' totalCount\n' + 133 | ' }\n' + 134 | ' \n' + 135 | ' # size of repository\n' + 136 | ' diskUsage\n' + 137 | ' \n' + 138 | ' # pull requests number\n' + 139 | ' pullRequestsOpen: pullRequests(states: OPEN){ \n' + 140 | ' totalCount\n' + 141 | ' }\n' + 142 | ' pullRequestsClosed: pullRequests(states: CLOSED){\n' + 143 | ' totalCount\n' + 144 | ' }\n' + 145 | ' pullRequestsMerged: pullRequests(states: MERGED){\n' + 146 | ' totalCount\n' + 147 | ' }\n' + 148 | '\n' + 149 | ' # total number of comments and commits for last open 100 PRs\n' + 150 | ' PROpenCommentsCommitsCount: pullRequests(last:100, states: OPEN){\n' + 151 | ' edges{\n' + 152 | ' node{\n' + 153 | ' comments{\n' + 154 | ' totalCount\n' + 155 | ' }\n' + 156 | ' commits{\n' + 157 | ' totalCount\n' + 158 | ' } \n' + 159 | ' }\n' + 160 | ' }\n' + 161 | ' }\n' + 162 | ' \n' + 163 | ' # total number of comments and commits for last 100 closed PRs\n' + 164 | ' PRClosedCommentsCommitsCount: pullRequests(last:100, states: CLOSED){\n' + 165 | ' edges{\n' + 166 | ' node{\n' + 167 | ' comments{\n' + 168 | ' totalCount\n' + 169 | ' }\n' + 170 | ' commits{\n' + 171 | ' totalCount\n' + 172 | ' } \n' + 173 | ' }\n' + 174 | ' }\n' + 175 | ' }\n' + 176 | ' \n' + 177 | ' # total number of comments and commits for last 100 merged PRs\n' + 178 | ' PRMergedCommentsCommitsCount: pullRequests(last:100, states: MERGED){\n' + 179 | ' edges{\n' + 180 | ' node{\n' + 181 | ' comments{\n' + 182 | ' totalCount\n' + 183 | ' }\n' + 184 | ' commits{\n' + 185 | ' totalCount\n' + 186 | ' } \n' + 187 | ' }\n' + 188 | ' }\n' + 189 | ' }\n' + 190 | ' \n' + 191 | ' # issues number\n' + 192 | ' issuesOpen:issues(states:OPEN){\n' + 193 | ' totalCount\n' + 194 | ' }\n' + 195 | ' issuesClosed:issues(states:CLOSED){\n' + 196 | ' totalCount\n' + 197 | ' }\n' + 198 | ' \n' + 199 | ' # number of comments on last 100 open issues\n' + 200 | ' iOpenCommentsParticipantsCount: issues(last: 100, states:OPEN){\n' + 201 | ' edges{\n' + 202 | ' node{\n' + 203 | ' comments{\n' + 204 | ' totalCount\n' + 205 | ' }\n' + 206 | ' participants{\n' + 207 | ' totalCount\n' + 208 | ' } \n' + 209 | ' }\n' + 210 | ' }\n' + 211 | ' }\n' + 212 | ' \n' + 213 | ' # number of comments on last 100 closed issues\n' + 214 | ' iClosedCommentsParticipantsCount: issues(last: 100, states:CLOSED){\n' + 215 | ' edges{\n' + 216 | ' node{\n' + 217 | ' comments{\n' + 218 | ' totalCount\n' + 219 | ' }\n' + 220 | ' participants{\n' + 221 | ' totalCount\n' + 222 | ' } \n' + 223 | ' }\n' + 224 | ' }\n' + 225 | ' }\n' + 226 | ' \n' + 227 | ' # total number of branches\n' + 228 | ' numBranches:refs(refPrefix: "refs/heads/") {\n' + 229 | ' totalCount \n' + 230 | ' }\n' + 231 | ' \n' + 232 | ' # total commits on master branch\n' + 233 | ' numCommits:ref(qualifiedName: "master"){\n' + 234 | ' target{\n' + 235 | ' ... on Commit{\n' + 236 | ' history{\n' + 237 | ' totalCount\n' + 238 | ' }\n' + 239 | ' }\n' + 240 | ' }\n' + 241 | ' }\n' + 242 | ' \n' + 243 | ' # total number of tags\n' + 244 | ' tags:refs(refPrefix:"refs/tags/"){\n' + 245 | ' totalCount\n' + 246 | ' }\n' + 247 | ' \n' + 248 | ' # total number of releases\n' + 249 | ' releases {\n' + 250 | ' \ttotalCount \n' + 251 | ' }\n' + 252 | ' }\n' + 253 | '}\n'; 254 | return q; 255 | } 256 | 257 | //get query for rateLimit enquiry 258 | function getRateLimitQuery() { 259 | let q = "{\n" + 260 | " viewer {\n" + 261 | " login\n" + 262 | " }\n" + 263 | " rateLimit {\n" + 264 | " limit\n" + 265 | " cost\n" + 266 | " remaining\n" + 267 | " resetAt\n" + 268 | " }\n" + 269 | "}"; 270 | return q; 271 | } 272 | 273 | let start = parseInt(process.env.START), end = parseInt(process.env.END); 274 | let fMid = "" + start + "_" + end; 275 | let input = "./repos/file_2008-01-01_2018-02-15.csv", output = "./graphQlData/file_" + fMid + ".json"; 276 | let nReq = -1, nRes = -1, setI, reqSetI; 277 | let basicData = [], graphQLData = [], errors = 0, errorsList = []; 278 | let startTime = new Date(); 279 | const query = getQuery(); 280 | 281 | // const query = getRateLimitQuery(); 282 | 283 | 284 | function readData() { 285 | console.log("reading csv data from " + input + "..."); 286 | csv().fromFile(input).on('json', (jsonObj) => { 287 | basicData.push(jsonObj); 288 | }) 289 | .on('done', (error) => { 290 | //error handling 291 | if (error) { 292 | return console.log(error); 293 | } 294 | 295 | // slicing the data 296 | basicData = basicData.slice(start, end + 1); 297 | console.log('done reading data! having length ' + basicData.length + " from " + start + " to " + end); 298 | 299 | //starting the request cycle 300 | console.log("starting to fetch data..."); 301 | reqSetI = setInterval(callRequest, parseInt(process.env.LOOPDELAY)); 302 | }); 303 | } 304 | 305 | function callRequest() { 306 | if (nReq === basicData.length - 1) { 307 | clearInterval(reqSetI); 308 | console.log("Task completed"); 309 | // saving data 310 | setI = setInterval(() => { 311 | if (nRes === nReq) { 312 | console.log("total requests: " + nReq + "\ttotal responses: " + nRes 313 | + "\tdataCount: " + graphQLData.length + "\terrors count: " + errors); 314 | console.log("errorList: ", errorsList); 315 | return saveData(); 316 | } 317 | }, 10 * 1000); 318 | return; 319 | } 320 | 321 | nReq++; 322 | let myReq = nReq; 323 | let repo = basicData[myReq]; 324 | let variables = { 325 | "owner": repo["ownerName"], 326 | "name": repo["RepoName"], 327 | "isUser": repo["Type"] === "User", 328 | }; 329 | // console.log(variables); 330 | client 331 | .request(query, variables) 332 | .then(data => { 333 | data["repository"]["type"] = variables["isUser"] ? "user" : "organization"; 334 | data["siteAdmin"] = repo["SideAdmin"]; 335 | graphQLData.push(data); 336 | nRes++; 337 | console.log("got " + nRes + " response for reqNum " + myReq + "\ttotal data len: " + (graphQLData.length) 338 | + "\terrors: " + errors + "\tat: " + (new Date() - startTime) / 1000.0 + "s"); 339 | }) 340 | .catch((err) => { 341 | nRes++; 342 | console.log("got error on " + myReq + " data! ************************************"); 343 | errors++; 344 | errorsList.push(myReq); 345 | console.log(err.response); 346 | }); 347 | } 348 | 349 | function saveData() { 350 | clearInterval(setI); 351 | console.log("saving data having length: " + graphQLData.length + " to " + output + "..."); 352 | jsonfile.writeFile(output, graphQLData, function (err) { 353 | if (err) { 354 | return console.log(err); 355 | } 356 | console.log("done saving! " + graphQLData.length + " items"); 357 | }) 358 | } 359 | 360 | function callRateLimitRequest() { 361 | client 362 | .request(query) 363 | .then(data => { 364 | console.log(data); 365 | console.log("fetched!"); 366 | }) 367 | .catch((err) => { 368 | console.log("error: "); 369 | console.log(err.response) 370 | }); 371 | } 372 | 373 | //starting to read data 374 | readData(); 375 | // callRateLimitRequest(); -------------------------------------------------------------------------------- /scripts/nodejs/githubGraphQLApiCallsDO_V3.js: -------------------------------------------------------------------------------- 1 | //request-response-request based implementation 2 | 3 | const fs = require('fs'); 4 | const csv = require('csvtojson'); 5 | const jsonfile = require("jsonfile"); 6 | const dotenv = require("dotenv"); 7 | dotenv.config(); 8 | dotenv.load(); 9 | const {request, GraphQLClient} = require('graphql-request'); 10 | let url = "https://api.github.com/graphql"; 11 | const client = new GraphQLClient(url, { 12 | headers: { 13 | Authorization: 'bearer ' + process.env.TOKEN, 14 | }, 15 | }); 16 | 17 | // get query for data 18 | function getQuery() { 19 | let q = 'query ($owner: String!, $name: String!, $isUser:Boolean!) { \n' + 20 | ' \n' + 21 | ' organization(login: $owner) @skip(if: $isUser){\n' + 22 | ' login\n' + 23 | ' \n' + 24 | ' repositories{\n' + 25 | ' totalCount\n' + 26 | ' } \n' + 27 | ' \n' + 28 | ' location\t\t#location of organization\n' + 29 | ' \n' + 30 | ' members{\n' + 31 | ' totalCount\n' + 32 | ' }\n' + 33 | ' \n' + 34 | ' websiteUrl \n' + 35 | ' }\n' + 36 | ' \n' + 37 | ' user(login: $owner) @include(if: $isUser){ \n' + 38 | ' login\n' + 39 | ' \n' + 40 | ' followers{\t\t# number of followers of the user\n' + 41 | ' totalCount\n' + 42 | ' } \n' + 43 | '\trepositories{\t\t# number of repositories of the user\n' + 44 | ' totalCount\n' + 45 | ' }\n' + 46 | ' \n' + 47 | ' following{\t# following\n' + 48 | ' totalCount\n' + 49 | ' }\n' + 50 | ' \n' + 51 | ' location # location of user\n' + 52 | ' \n' + 53 | ' organizations{\n' + 54 | ' totalCount\n' + 55 | ' }\n' + 56 | ' \n' + 57 | ' gists(last:100){\n' + 58 | ' edges{\n' + 59 | ' node{ \n' + 60 | ' comments{\n' + 61 | ' totalCount\n' + 62 | ' }\n' + 63 | ' stargazers{\n' + 64 | ' totalCount\n' + 65 | ' } \n' + 66 | ' }\n' + 67 | ' }\n' + 68 | ' totalCount\n' + 69 | ' } \n' + 70 | ' \n' + 71 | ' websiteUrl\n' + 72 | ' }\n' + 73 | ' \n' + 74 | ' repository(owner: $owner, name: $name) {\n' + 75 | ' name\t\t# name of the repo \n' + 76 | '\n' + 77 | ' primaryLanguage{\n' + 78 | ' name\n' + 79 | ' }\n' + 80 | '\n' + 81 | ' license\n' + 82 | ' \n' + 83 | ' isArchived\n' + 84 | '\n' + 85 | ' hasWikiEnabled\n' + 86 | ' \n' + 87 | ' forkCount\n' + 88 | ' \n' + 89 | ' # readme.md of the repo\n' + 90 | ' readme_md:object(expression: "master:README.md"){\n' + 91 | ' ... on Blob{\n' + 92 | ' text\n' + 93 | ' byteSize\n' + 94 | ' }\n' + 95 | ' }\n' + 96 | ' readme_txt:object(expression: "master:README.txt"){\n' + 97 | ' ... on Blob{\n' + 98 | ' text\n' + 99 | ' byteSize\n' + 100 | ' }\n' + 101 | ' }\n' + 102 | ' readme_markdown:object(expression: "master:README.markdown"){\n' + 103 | ' ... on Blob{\n' + 104 | ' text\n' + 105 | ' byteSize\n' + 106 | ' }\n' + 107 | ' }\n' + 108 | ' readme_tst:object(expression: "master:README.tst"){\n' + 109 | ' ... on Blob{\n' + 110 | ' text\n' + 111 | ' byteSize\n' + 112 | ' }\n' + 113 | ' }\n' + 114 | ' readme_:object(expression: "master:README"){\n' + 115 | ' ... on Blob{\n' + 116 | ' text\n' + 117 | ' byteSize\n' + 118 | ' }\n' + 119 | ' }\n' + 120 | ' \n' + 121 | ' stars: stargazers{\n' + 122 | ' totalCount\n' + 123 | ' }\n' + 124 | ' createdAt\n' + 125 | ' updatedAt\n' + 126 | ' pushedAt\n' + 127 | '\n' + 128 | ' \n' + 129 | ' description\n' + 130 | ' \n' + 131 | ' subscribersCount: watchers{\n' + 132 | ' totalCount\n' + 133 | ' }\n' + 134 | ' \n' + 135 | ' # size of repository\n' + 136 | ' diskUsage\n' + 137 | ' \n' + 138 | ' # pull requests number\n' + 139 | ' pullRequestsOpen: pullRequests(states: OPEN){ \n' + 140 | ' totalCount\n' + 141 | ' }\n' + 142 | ' pullRequestsClosed: pullRequests(states: CLOSED){\n' + 143 | ' totalCount\n' + 144 | ' }\n' + 145 | ' pullRequestsMerged: pullRequests(states: MERGED){\n' + 146 | ' totalCount\n' + 147 | ' }\n' + 148 | '\n' + 149 | ' # total number of comments and commits for last open 100 PRs\n' + 150 | ' PROpenCommentsCommitsCount: pullRequests(last:100, states: OPEN){\n' + 151 | ' edges{\n' + 152 | ' node{\n' + 153 | ' comments{\n' + 154 | ' totalCount\n' + 155 | ' }\n' + 156 | ' commits{\n' + 157 | ' totalCount\n' + 158 | ' } \n' + 159 | ' }\n' + 160 | ' }\n' + 161 | ' }\n' + 162 | ' \n' + 163 | ' # total number of comments and commits for last 100 closed PRs\n' + 164 | ' PRClosedCommentsCommitsCount: pullRequests(last:100, states: CLOSED){\n' + 165 | ' edges{\n' + 166 | ' node{\n' + 167 | ' comments{\n' + 168 | ' totalCount\n' + 169 | ' }\n' + 170 | ' commits{\n' + 171 | ' totalCount\n' + 172 | ' } \n' + 173 | ' }\n' + 174 | ' }\n' + 175 | ' }\n' + 176 | ' \n' + 177 | ' # total number of comments and commits for last 100 merged PRs\n' + 178 | ' PRMergedCommentsCommitsCount: pullRequests(last:100, states: MERGED){\n' + 179 | ' edges{\n' + 180 | ' node{\n' + 181 | ' comments{\n' + 182 | ' totalCount\n' + 183 | ' }\n' + 184 | ' commits{\n' + 185 | ' totalCount\n' + 186 | ' } \n' + 187 | ' }\n' + 188 | ' }\n' + 189 | ' }\n' + 190 | ' \n' + 191 | ' # issues number\n' + 192 | ' issuesOpen:issues(states:OPEN){\n' + 193 | ' totalCount\n' + 194 | ' }\n' + 195 | ' issuesClosed:issues(states:CLOSED){\n' + 196 | ' totalCount\n' + 197 | ' }\n' + 198 | ' \n' + 199 | ' # number of comments on last 100 open issues\n' + 200 | ' iOpenCommentsParticipantsCount: issues(last: 100, states:OPEN){\n' + 201 | ' edges{\n' + 202 | ' node{\n' + 203 | ' comments{\n' + 204 | ' totalCount\n' + 205 | ' }\n' + 206 | ' participants{\n' + 207 | ' totalCount\n' + 208 | ' } \n' + 209 | ' }\n' + 210 | ' }\n' + 211 | ' }\n' + 212 | ' \n' + 213 | ' # number of comments on last 100 closed issues\n' + 214 | ' iClosedCommentsParticipantsCount: issues(last: 100, states:CLOSED){\n' + 215 | ' edges{\n' + 216 | ' node{\n' + 217 | ' comments{\n' + 218 | ' totalCount\n' + 219 | ' }\n' + 220 | ' participants{\n' + 221 | ' totalCount\n' + 222 | ' } \n' + 223 | ' }\n' + 224 | ' }\n' + 225 | ' }\n' + 226 | ' \n' + 227 | ' # total number of branches\n' + 228 | ' numBranches:refs(refPrefix: "refs/heads/") {\n' + 229 | ' totalCount \n' + 230 | ' }\n' + 231 | ' \n' + 232 | ' # total commits on master branch\n' + 233 | ' numCommits:ref(qualifiedName: "master"){\n' + 234 | ' target{\n' + 235 | ' ... on Commit{\n' + 236 | ' history{\n' + 237 | ' totalCount\n' + 238 | ' }\n' + 239 | ' }\n' + 240 | ' }\n' + 241 | ' }\n' + 242 | ' \n' + 243 | ' # total number of tags\n' + 244 | ' tags:refs(refPrefix:"refs/tags/"){\n' + 245 | ' totalCount\n' + 246 | ' }\n' + 247 | ' \n' + 248 | ' # total number of releases\n' + 249 | ' releases {\n' + 250 | ' \ttotalCount \n' + 251 | ' }\n' + 252 | ' }\n' + 253 | '}\n'; 254 | return q; 255 | } 256 | 257 | //get query for rateLimit enquiry 258 | function getRateLimitQuery() { 259 | let q = "{\n" + 260 | " viewer {\n" + 261 | " login\n" + 262 | " }\n" + 263 | " rateLimit {\n" + 264 | " limit\n" + 265 | " cost\n" + 266 | " remaining\n" + 267 | " resetAt\n" + 268 | " }\n" + 269 | "}"; 270 | return q; 271 | } 272 | 273 | let start = parseInt(process.env.START), end = parseInt(process.env.END); 274 | let fMid = "" + start + "_" + end; 275 | let input = "./repos/file_2008-01-01_2018-02-15.csv", output = "./graphQlData/file_" + fMid + ".json"; 276 | let nReq = -1, nRes = -1; 277 | let basicData = [], graphQLData = [], errors = 0, errorsList = []; 278 | let startTime = new Date(); 279 | const query = getQuery(); 280 | 281 | // const query = getRateLimitQuery(); 282 | 283 | 284 | function readData() { 285 | console.log("reading csv data from " + input + "..."); 286 | csv().fromFile(input).on('json', (jsonObj) => { 287 | basicData.push(jsonObj); 288 | }) 289 | .on('done', (error) => { 290 | //error handling 291 | if (error) { 292 | return console.log(error); 293 | } 294 | 295 | // slicing the data 296 | basicData = basicData.slice(start, end + 1); 297 | console.log('done reading data! having length ' + basicData.length + " from " + start + " to " + end); 298 | 299 | //starting the request cycle 300 | console.log("starting to fetch data..."); 301 | callRequest(); 302 | }); 303 | } 304 | 305 | function callRequest() { 306 | if (nReq === basicData.length - 1) { 307 | console.log("Task completed"); 308 | // saving data 309 | console.log("total requests: " + nReq + "\ttotal responses: " + nRes 310 | + "\tdataCount: " + graphQLData.length + "\terrors count: " + errors); 311 | console.log("errorList: ", errorsList); 312 | return saveData(); 313 | } 314 | 315 | nReq++; 316 | let myReq = nReq; 317 | let repo = basicData[myReq]; 318 | let variables = { 319 | "owner": repo["ownerName"], 320 | "name": repo["RepoName"], 321 | "isUser": repo["Type"] === "User", 322 | }; 323 | // console.log(variables); 324 | client 325 | .request(query, variables) 326 | .then(data => { 327 | data["repository"]["type"] = variables["isUser"] ? "user" : "organization"; 328 | data["siteAdmin"] = repo["SideAdmin"]; 329 | graphQLData.push(data); 330 | nRes++; 331 | console.log("got " + nRes + " response for reqNum " + myReq + "\ttotal data len: " + (graphQLData.length) 332 | + "\terrors: " + errors + "\tat: " + (new Date() - startTime) / 1000.0 + "s"); 333 | callRequest(); 334 | }) 335 | .catch((err) => { 336 | nRes++; 337 | console.log("got error on " + myReq + " data! ************************************"); 338 | errors++; 339 | errorsList.push(myReq); 340 | console.log(err.response); 341 | callRequest(); 342 | }); 343 | } 344 | 345 | function saveData() { 346 | console.log("saving data having length: " + graphQLData.length + " to " + output + "..."); 347 | jsonfile.writeFile(output, graphQLData, function (err) { 348 | if (err) { 349 | return console.log(err); 350 | } 351 | console.log("done saving! " + graphQLData.length + " items"); 352 | }) 353 | } 354 | 355 | function callRateLimitRequest() { 356 | client 357 | .request(query) 358 | .then(data => { 359 | console.log(data); 360 | console.log("fetched!"); 361 | }) 362 | .catch((err) => { 363 | console.log("error: "); 364 | console.log(err.response) 365 | }); 366 | } 367 | 368 | //starting to read data 369 | readData(); 370 | // callRateLimitRequest(); -------------------------------------------------------------------------------- /scripts/nodejs/graphql queries: -------------------------------------------------------------------------------- 1 | query ($owner: String!, $name: String!, $isUser:Boolean!) { 2 | 3 | organization(login: $owner) @skip(if: $isUser){ 4 | login 5 | 6 | repositories{ 7 | totalCount 8 | } 9 | 10 | location #location of organization 11 | 12 | members{ 13 | totalCount 14 | } 15 | 16 | websiteUrl 17 | } 18 | 19 | user(login: $owner) @include(if: $isUser){ 20 | login 21 | 22 | followers{ # number of followers of the user 23 | totalCount 24 | } 25 | repositories{ # number of repositories of the user 26 | totalCount 27 | } 28 | 29 | following{ # following 30 | totalCount 31 | } 32 | 33 | location # location of user 34 | 35 | organizations{ 36 | totalCount 37 | } 38 | 39 | gists(last:100){ 40 | edges{ 41 | node{ 42 | comments{ 43 | totalCount 44 | } 45 | stargazers{ 46 | totalCount 47 | } 48 | } 49 | } 50 | totalCount 51 | } 52 | 53 | websiteUrl 54 | } 55 | 56 | repository(owner: $owner, name: $name) { 57 | name # name of the repo 58 | 59 | primaryLanguage{ 60 | name 61 | } 62 | 63 | license 64 | 65 | isArchived 66 | 67 | hasWikiEnabled 68 | 69 | forkCount 70 | 71 | # readme.md of the repo 72 | readme_md:object(expression: "master:README.md"){ 73 | ... on Blob{ 74 | text 75 | byteSize 76 | } 77 | } 78 | readme_txt:object(expression: "master:README.txt"){ 79 | ... on Blob{ 80 | text 81 | byteSize 82 | } 83 | } 84 | readme_markdown:object(expression: "master:README.markdown"){ 85 | ... on Blob{ 86 | text 87 | byteSize 88 | } 89 | } 90 | readme_tst:object(expression: "master:README.tst"){ 91 | ... on Blob{ 92 | text 93 | byteSize 94 | } 95 | } 96 | readme_:object(expression: "master:README"){ 97 | ... on Blob{ 98 | text 99 | byteSize 100 | } 101 | } 102 | 103 | stars: stargazers{ 104 | totalCount 105 | } 106 | createdAt 107 | updatedAt 108 | pushedAt 109 | 110 | 111 | description 112 | 113 | subscribersCount: watchers{ 114 | totalCount 115 | } 116 | 117 | # size of repository 118 | diskUsage 119 | 120 | # pull requests number 121 | pullRequestsOpen: pullRequests(states: OPEN){ 122 | totalCount 123 | } 124 | pullRequestsClosed: pullRequests(states: CLOSED){ 125 | totalCount 126 | } 127 | pullRequestsMerged: pullRequests(states: MERGED){ 128 | totalCount 129 | } 130 | 131 | # total number of comments and commits for last open 100 PRs 132 | PROpenCommentsCommitsCount: pullRequests(last:100, states: OPEN){ 133 | edges{ 134 | node{ 135 | comments{ 136 | totalCount 137 | } 138 | commits{ 139 | totalCount 140 | } 141 | } 142 | } 143 | } 144 | 145 | # total number of comments and commits for last 100 closed PRs 146 | PRClosedCommentsCommitsCount: pullRequests(last:100, states: CLOSED){ 147 | edges{ 148 | node{ 149 | comments{ 150 | totalCount 151 | } 152 | commits{ 153 | totalCount 154 | } 155 | } 156 | } 157 | } 158 | 159 | # total number of comments and commits for last 100 merged PRs 160 | PRMergedCommentsCommitsCount: pullRequests(last:100, states: MERGED){ 161 | edges{ 162 | node{ 163 | comments{ 164 | totalCount 165 | } 166 | commits{ 167 | totalCount 168 | } 169 | } 170 | } 171 | } 172 | 173 | # issues number 174 | issuesOpen:issues(states:OPEN){ 175 | totalCount 176 | } 177 | issuesClosed:issues(states:CLOSED){ 178 | totalCount 179 | } 180 | 181 | # number of comments on last 100 open issues 182 | iOpenCommentsParticipantsCount: issues(last: 100, states:OPEN){ 183 | edges{ 184 | node{ 185 | comments{ 186 | totalCount 187 | } 188 | participants{ 189 | totalCount 190 | } 191 | } 192 | } 193 | } 194 | 195 | # number of comments on last 100 closed issues 196 | iClosedCommentsParticipantsCount: issues(last: 100, states:CLOSED){ 197 | edges{ 198 | node{ 199 | comments{ 200 | totalCount 201 | } 202 | participants{ 203 | totalCount 204 | } 205 | } 206 | } 207 | } 208 | 209 | # total number of branches 210 | numBranches:refs(refPrefix: "refs/heads/") { 211 | totalCount 212 | } 213 | 214 | # total commits on master branch 215 | numCommits:ref(qualifiedName: "master"){ 216 | target{ 217 | ... on Commit{ 218 | history{ 219 | totalCount 220 | } 221 | } 222 | } 223 | } 224 | 225 | # total number of tags 226 | tags:refs(refPrefix:"refs/tags/"){ 227 | totalCount 228 | } 229 | 230 | # total number of releases 231 | releases { 232 | totalCount 233 | } 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /scripts/nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "git-star-predictor", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Get-Contributors.js", 6 | "dependencies": { 7 | "csvtojson": "^1.1.9", 8 | "dateformat": "^3.0.3", 9 | "dotenv": "^5.0.0", 10 | "graphql-request": "^1.4.1", 11 | "json2csv": "^3.11.5", 12 | "jsonfile": "^4.0.0", 13 | "request": "^2.83.0" 14 | }, 15 | "devDependencies": {}, 16 | "scripts": { 17 | "test": "echo \"Error: no test specified\" && exit 1" 18 | }, 19 | "author": "", 20 | "license": "ISC" 21 | } 22 | -------------------------------------------------------------------------------- /scripts/nodejs/test.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/dc8c16a0516fe85ec130caadde5c577493860cb6/scripts/nodejs/test.js -------------------------------------------------------------------------------- /scripts/nodejs/test3.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doodies/Github-Stars-Predictor/dc8c16a0516fe85ec130caadde5c577493860cb6/scripts/nodejs/test3.js -------------------------------------------------------------------------------- /scripts/python/json_to_csv.py: -------------------------------------------------------------------------------- 1 | import json 2 | from pprint import pprint 3 | import pandas as pd 4 | import sys 5 | import re 6 | import os 7 | 8 | reload(sys) 9 | sys.setdefaultencoding('utf-8') 10 | 11 | user_values = [] 12 | org_values = [] 13 | user_col = [] 14 | org_col = [] 15 | 16 | isEmptyUser = True 17 | isEmptyOrg = True 18 | 19 | def isReadmeFileExist(repo): 20 | value = '' 21 | find = False 22 | for readme in repo.keys(): 23 | if str(readme).startswith('readme'): 24 | if i['repository'][str(readme)] != None and len(i['repository'][str(readme)]) > 0: 25 | find = True 26 | value = readme 27 | 28 | return value if find else None 29 | def handle_gist(gists): 30 | gists = gists['edges'] 31 | gistStars = 0 32 | gistComments = 0 33 | for gist in gists: 34 | gistStars += gist['node']['stargazers']['totalCount'] 35 | gistComments += gist['node']['comments']['totalCount'] 36 | return gistStars, gistComments 37 | 38 | def handle_pr(pr): 39 | pr = pr['edges'] 40 | prComments = 0 41 | prCommits = 0 42 | for p in pr: 43 | prComments += p['node']['comments']['totalCount'] 44 | prCommits += p['node']['commits']['totalCount'] 45 | # print(str(pr['node']['comments']['totalCount'])) 46 | return prCommits, prComments 47 | 48 | def handle_issues(issues): 49 | issues = issues['edges'] 50 | issuesComments = 0 51 | issuesParticipants = 0 52 | for issue in issues: 53 | issuesComments += issue['node']['comments']['totalCount'] 54 | issuesParticipants += issue['node']['participants']['totalCount'] 55 | return issuesParticipants, issuesComments 56 | 57 | def handle_readme(string): 58 | links_count = len(re.findall(r'(https?://[^\s]+)', string)) 59 | word_count = len(re.findall(r'\w+', string)) 60 | char_count = len(string) 61 | return char_count, word_count, links_count 62 | 63 | def handle_objects(obj): 64 | global isEmptyUser 65 | global isEmptyOrg 66 | global user_values 67 | global org_values 68 | global user_col 69 | global org_col 70 | data_dict = {} 71 | 72 | data_dict['siteAdmin'] = obj['siteAdmin'] 73 | 74 | repo = obj['repository'] 75 | # print repo 76 | 77 | data_dict['reponame'] = str(repo['name']) 78 | data_dict['createdAt'] = repo['createdAt'] 79 | data_dict['pushedAt'] = repo['pushedAt'] 80 | data_dict['updatedAt'] = repo['updatedAt'] 81 | data_dict['description'] = repo['description'] 82 | data_dict['diskUsage'] = repo['diskUsage'] 83 | data_dict['forkCount'] = repo['forkCount'] 84 | data_dict['hasWikiEnabled'] = repo['hasWikiEnabled'] 85 | data_dict['isArchived'] = repo['isArchived'] 86 | data_dict['issuesClosed'] = repo['issuesClosed']['totalCount'] 87 | data_dict['issuesOpen'] = repo['issuesOpen']['totalCount'] 88 | data_dict['license'] = repo['license'] if repo['license'] is not None else "" 89 | data_dict['primaryLanguage'] = repo['primaryLanguage']['name'] if repo['primaryLanguage'] is not None else "" 90 | data_dict['prClosed'] = repo['pullRequestsClosed']['totalCount'] 91 | data_dict['prMerged'] = repo['pullRequestsMerged']['totalCount'] 92 | data_dict['prOpen'] = repo['pullRequestsOpen']['totalCount'] 93 | data_dict['releases'] = repo['releases']['totalCount'] 94 | data_dict['stars'] = repo['stars']['totalCount'] 95 | data_dict['subscribersCount'] = repo['subscribersCount']['totalCount'] 96 | data_dict['tags'] = repo['tags']['totalCount'] 97 | data_dict['branches'] = repo['numBranches']['totalCount'] 98 | data_dict['commits'] = repo['numCommits']['target']['history']['totalCount'] if repo['numCommits'] is not None else "" 99 | data_dict['prMergedCommits'], data_dict['prMergedComments'] = handle_pr(repo['PRMergedCommentsCommitsCount']) 100 | data_dict['prOpenCommits'], data_dict['prOpenComments'] = handle_pr(repo['PROpenCommentsCommitsCount']) 101 | data_dict['prClosedCommits'], data_dict['prClosedComments'] = handle_pr(repo['PRClosedCommentsCommitsCount']) 102 | data_dict['iOpenParticipants'], data_dict['iOpenComments'] = handle_issues(repo['iOpenCommentsParticipantsCount']) 103 | data_dict['iClosedParticipants'], data_dict['iClosedComments'] = handle_issues(repo['iClosedCommentsParticipantsCount']) 104 | data_dict['type'] = repo['type'] 105 | 106 | # Handle the readme file 107 | 108 | data_dict["readmeCharCount"] = 0 109 | data_dict["readmeWordCount"] = 0 110 | data_dict["readmeLinkCount"] = 0 111 | data_dict["readmeSize"] = 0 112 | 113 | readmeExt = isReadmeFileExist(repo) 114 | if readmeExt != None: 115 | # print readmeExt 116 | data_dict['readmeSize'] = repo[readmeExt]["byteSize"] 117 | data_dict['readmeCharCount'], data_dict['readmeWordCount'], data_dict['readmeLinkCount'] = handle_readme(repo[readmeExt]['text']) 118 | 119 | 120 | 121 | # if the repo from the user 122 | if obj.keys()[0] == 'user': 123 | user = obj['user'] 124 | # pprint(user) 125 | data_dict['login'] = user['login'] 126 | data_dict['followers'] = user["followers"]["totalCount"] 127 | data_dict['following'] = user["following"]["totalCount"] 128 | data_dict['gists'] = user['gists']['totalCount'] 129 | data_dict['gistStar'], data_dict['gistComments'] = handle_gist(user['gists']) 130 | data_dict['location'] = user['location'] 131 | data_dict['organizations'] = user["organizations"]["totalCount"] 132 | data_dict['repositories'] = user["repositories"]["totalCount"] 133 | data_dict['websiteUrl'] = user["websiteUrl"] 134 | 135 | if isEmptyUser: 136 | user_col = list(data_dict.keys()) 137 | isEmptyUser = False 138 | user_values.append(list(data_dict.values())) 139 | 140 | # if the repository from the organization 141 | elif obj.keys()[0] == 'organization': 142 | org = obj['organization'] 143 | data_dict['login'] = org['login'] 144 | data_dict['websiteUrl'] = org['websiteUrl'] 145 | data_dict['members'] = org['members']["totalCount"] 146 | data_dict['location'] = org['location'] 147 | data_dict['repositories'] = org["repositories"]["totalCount"] 148 | 149 | if isEmptyOrg: 150 | org_col = list(data_dict.keys()) 151 | isEmptyOrg = False 152 | org_values.append(list(data_dict.values())) 153 | 154 | 155 | def save_files(file_name): 156 | file_name += '.csv' 157 | global user_col 158 | global org_col 159 | global user_values 160 | global org_values 161 | df_user = pd.DataFrame(data = user_values, columns = user_col) 162 | df_org = pd.DataFrame(data = org_values, columns = org_col) 163 | # print("\nsaving..... user dataframe") 164 | # df_user.to_csv('user.csv', index = False) 165 | # print("\nsaving..... org dataframe") 166 | # df_org.to_csv('org.csv', index = False) 167 | 168 | merge = df_user.append(df_org) 169 | print("\nsaving..... + " + file_name + " dataframe") 170 | merge.to_csv(file_name, index = False) 171 | 172 | # # user data 173 | # # pprint(repo) 174 | 175 | 176 | 177 | # # if isEmpty: 178 | # # df = pd.DataFrame(columns = list(data_dict.keys())) 179 | # # isEmpty = False 180 | # # append the row to the pandas dataframe 181 | # df.loc[df.index.max() + 1, list(data_dict.keys())] = list(data_dict.values()) 182 | # pprint(data_dict) 183 | 184 | 185 | # count = 0 186 | # for i in data: 187 | # if i['repository']['object'] == None: 188 | # count+=1 189 | # print count 190 | 191 | # print(len(data_dict)) 192 | # print(createdAt,pushedAt,updatedAt,diskUsage,forkCount,hasWikiEnabled,isArchived,issuesClosed,issuesOpen,license,primaryLanguage,prClosed,prMerged,prOpen,releases,stars,subscribersCount,tags) 193 | # handle_objects(data[2]) 194 | 195 | # print(data) 196 | 197 | 198 | # for i, j in zip(data[0]["user"].keys(), data[4]["organization"].keys()): 199 | # print "{0: <32} {1: <32}".format(i, j) 200 | 201 | 202 | # print data[0] 203 | 204 | 205 | 206 | 207 | path = os.getcwd() + "/" 208 | json_files = [] 209 | files = os.listdir(path) 210 | for file in files: 211 | if os.path.splitext(path + file)[1] == '.json': 212 | json_files.append(file) 213 | 214 | print '---------------------------- total files : ' + str(len(json_files)) 215 | for file in json_files: 216 | user_values = [] 217 | org_values = [] 218 | user_col = [] 219 | org_col = [] 220 | 221 | isEmptyUser = True 222 | isEmptyOrg = True 223 | data = json.load(open(path + file)) 224 | count = 0 225 | print '----------------- ' + str(file) + ' -----------------------' 226 | for i in data: 227 | if count % 1000 == 0 and count !=0: 228 | print 'rows :' + str(count) 229 | handle_objects(i) 230 | count+=1 231 | save_files(file[:-5]) 232 | 233 | 234 | # for i in data[0]['repository'].keys(): 235 | # print i + " " + str(data[0]['repository'][i]) 236 | # print(data[2]["organization"].keys()) 237 | 238 | -------------------------------------------------------------------------------- /scripts/python/merge.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import os 3 | import sys 4 | 5 | merge_file_name = sys.argv[1] 6 | if '.csv' not in merge_file_name: 7 | merge_file_name += '.csv' 8 | 9 | path = os.getcwd() + "/" 10 | csv_files = [] 11 | files = os.listdir(path) 12 | for file in files: 13 | if os.path.splitext(path + file)[1] == '.csv': 14 | csv_files.append(file) 15 | 16 | print '----------------------- total files : ' + str(len(csv_files)) 17 | df_dict = {} 18 | total_files = len(csv_files) 19 | for index in range(total_files): 20 | df_dict["df"+str(index)] = pd.read_csv(path + csv_files[index]) 21 | 22 | temp = pd.DataFrame() 23 | for i in range(total_files): 24 | temp = temp.append(df_dict["df"+str(i)]) 25 | print(csv_files[i] + " shape:" + str(df_dict["df"+str(i)].shape)) 26 | 27 | print("------------------\n") 28 | print("final_shape :"+str(temp.shape)) 29 | temp.to_csv(merge_file_name, index = False) 30 | --------------------------------------------------------------------------------