├── Aula 01.pdf ├── img ├── eda.png ├── ml.png ├── nmf.png ├── re.png ├── tf.png ├── cifar.png ├── iris.png ├── json.png ├── mnist.png ├── model.jpg ├── tree.png ├── imagenet.png ├── no_brain.jpg ├── overfit.png ├── kaggle_lb.png ├── train_test.png ├── classif_regr.png ├── random_forest.png ├── eval_santander.png ├── standardscaler.png ├── kernel_overfitting │ ├── mem2.jpg │ ├── meme1.jpeg │ ├── stack.png │ ├── combine.jpg │ ├── outlier.png │ ├── creativity.jpg │ ├── few_samples.png │ ├── under_over.png │ ├── outl_detection.png │ ├── isolation_forest.jpg │ ├── logisticregression.png │ └── overfitting_curve.png └── tree.dot ├── Aula08 ├── atividade_aula.png ├── templates │ └── base.html ├── static │ ├── style.css │ ├── script.js │ └── jquery.js └── aula8.py ├── README.md ├── Aula 07.ipynb ├── .ipynb_checkpoints └── Processamento de linguagem natural e mineração de dados textuais-checkpoint.ipynb └── Aula 04.ipynb /Aula 01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/Aula 01.pdf -------------------------------------------------------------------------------- /img/eda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/eda.png -------------------------------------------------------------------------------- /img/ml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/ml.png -------------------------------------------------------------------------------- /img/nmf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/nmf.png -------------------------------------------------------------------------------- /img/re.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/re.png -------------------------------------------------------------------------------- /img/tf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/tf.png -------------------------------------------------------------------------------- /img/cifar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/cifar.png -------------------------------------------------------------------------------- /img/iris.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/iris.png -------------------------------------------------------------------------------- /img/json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/json.png -------------------------------------------------------------------------------- /img/mnist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/mnist.png -------------------------------------------------------------------------------- /img/model.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/model.jpg -------------------------------------------------------------------------------- /img/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/tree.png -------------------------------------------------------------------------------- /img/imagenet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/imagenet.png -------------------------------------------------------------------------------- /img/no_brain.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/no_brain.jpg -------------------------------------------------------------------------------- /img/overfit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/overfit.png -------------------------------------------------------------------------------- /img/kaggle_lb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/kaggle_lb.png -------------------------------------------------------------------------------- /img/train_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/train_test.png -------------------------------------------------------------------------------- /img/classif_regr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/classif_regr.png -------------------------------------------------------------------------------- /img/random_forest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/random_forest.png -------------------------------------------------------------------------------- /img/eval_santander.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/eval_santander.png -------------------------------------------------------------------------------- /img/standardscaler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/standardscaler.png -------------------------------------------------------------------------------- /Aula08/atividade_aula.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/Aula08/atividade_aula.png -------------------------------------------------------------------------------- /img/kernel_overfitting/mem2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/kernel_overfitting/mem2.jpg -------------------------------------------------------------------------------- /img/kernel_overfitting/meme1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/kernel_overfitting/meme1.jpeg -------------------------------------------------------------------------------- /img/kernel_overfitting/stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/kernel_overfitting/stack.png -------------------------------------------------------------------------------- /img/kernel_overfitting/combine.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/kernel_overfitting/combine.jpg -------------------------------------------------------------------------------- /img/kernel_overfitting/outlier.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/kernel_overfitting/outlier.png -------------------------------------------------------------------------------- /img/kernel_overfitting/creativity.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/kernel_overfitting/creativity.jpg -------------------------------------------------------------------------------- /img/kernel_overfitting/few_samples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/kernel_overfitting/few_samples.png -------------------------------------------------------------------------------- /img/kernel_overfitting/under_over.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/kernel_overfitting/under_over.png -------------------------------------------------------------------------------- /img/kernel_overfitting/outl_detection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/kernel_overfitting/outl_detection.png -------------------------------------------------------------------------------- /img/kernel_overfitting/isolation_forest.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/kernel_overfitting/isolation_forest.jpg -------------------------------------------------------------------------------- /img/kernel_overfitting/logisticregression.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/kernel_overfitting/logisticregression.png -------------------------------------------------------------------------------- /img/kernel_overfitting/overfitting_curve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafjaa/curso-mineracao-de-dados-aplicada/HEAD/img/kernel_overfitting/overfitting_curve.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mineração de Dados Aplicada 2 | 3 | Material do curso de Mineração de Dados Aplicada preparado para o projeto de extensão __Laboratório de Redes de Conhecimento__ (aprovado no edital PIAEX 003/2018) – Instituto Federal do Sudeste de Minas Gerais, Campus Barbacena. 4 | 5 | Prof. Rafael José de Alencar Almeida
6 | 7 | # 8 | 9 | 10 | -------------------------------------------------------------------------------- /Aula08/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Análise de notícias 5 | 6 | 7 | 8 | 9 |
10 |

Análise de notícias

11 |
12 | 13 |
14 | 15 |
16 | 17 |
18 | Análise em tempo real do texto: 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Aula08/static/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | 7 | header{ 8 | color: #fff; 9 | background: #457fca; 10 | background: -webkit-linear-gradient(to right, #5691c8, #457fca); 11 | background: linear-gradient(to right, #5691c8, #457fca); 12 | padding: 15px 0; 13 | text-align: center; 14 | text-shadow: 1px 1px 5px #555; 15 | margin-bottom: 25px; 16 | display: block; 17 | } 18 | 19 | #sec_txt{ 20 | width: calc(49% - 15px); 21 | float: left; 22 | padding-left: 15px; 23 | } 24 | 25 | #sec_analise{ 26 | width: calc(49% - 15px); 27 | float: right; 28 | padding-right: 15px; 29 | } 30 | 31 | #txt_area{ 32 | width: calc(100% - 20px); 33 | height: 75vh; 34 | padding: 10px; 35 | resize: none; 36 | } 37 | 38 | #chart{ 39 | display: block; 40 | margin-top: 15px; 41 | width: 100%; 42 | } 43 | 44 | @media(max-width: 900px){ 45 | /* Atividade extra */ 46 | } -------------------------------------------------------------------------------- /Aula08/static/script.js: -------------------------------------------------------------------------------- 1 | // Aguarda a página carregar 2 | function retorno_ajax(resp){ 3 | resp = JSON.parse(resp); 4 | console.log(resp['proba']); 5 | 6 | new Chart($('#chart'), { 7 | type: 'bar', 8 | data: { 9 | labels: ['Notícia sobre esporte', 'Notícia qualquer'], 10 | datasets: [ 11 | { 12 | backgroundColor: ['#3e95cd', '#3cba9f'], 13 | data: [resp['proba'], 1 - resp['proba']] 14 | } 15 | ] 16 | }, 17 | options: { 18 | legend: { display: false }, 19 | title: { 20 | display: true, 21 | text: 'Probabilidade da notícia ser sobre esporte' 22 | } 23 | } 24 | }); 25 | } 26 | 27 | 28 | $(document).ready(function(){ 29 | 30 | $('#txt_area').on('change keyup paste', function() { 31 | 32 | // Obtém o conteúdo 33 | var txt = $(this).val(); 34 | 35 | // Envia o conteúdo via AJAX 36 | $.ajax({ 37 | type: 'POST', 38 | url: '/analisa_noticia', 39 | data: {'txt': txt}, 40 | success: retorno_ajax 41 | }); 42 | 43 | // console.log(txt); 44 | }); 45 | }); -------------------------------------------------------------------------------- /Aula08/aula8.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from flask import Flask 4 | from flask import request 5 | from flask import render_template 6 | 7 | 8 | app = Flask(__name__) 9 | 10 | 11 | @app.route('/', methods=['GET']) 12 | def home(): 13 | if request.method == 'GET': 14 | return render_template('base.html') 15 | 16 | 17 | @app.route('/analisa_noticia', methods=['POST']) 18 | def api_analise(): 19 | txt = request.form.get('txt') 20 | print(txt) 21 | 22 | ''' 23 | Atividade: obter a probabilidade da notícia ser sobre esporte: 24 | 25 | 1) Preprocessar a notícia recebida (txt) 26 | 2) Vetorizar com o mesmo TfidfVectorizer usado no dataset de treino 27 | 3) Usar a matriz tf-idf de uma linha resultante como entrada do modelo 28 | Prever com predict_proba(X)[:,1] 29 | 4) Jogar o resultado na variável "proba" (abaixo) 30 | 31 | 32 | Dica: para persistir um modelo treinado, usar a biblioteca joblib: 33 | 34 | from sklearn.externals import joblib 35 | 36 | # Persistir 37 | joblib.dump(model, 'model.dat') 38 | 39 | # Carregar 40 | model = joblib.load('model.dat') 41 | 42 | ''' 43 | proba = 0.95 44 | 45 | return json.dumps({'proba': proba}) 46 | 47 | 48 | if __name__ == '__main__': 49 | app.run(debug=True) -------------------------------------------------------------------------------- /img/tree.dot: -------------------------------------------------------------------------------- 1 | digraph Tree { 2 | node [shape=box] ; 3 | 0 [label="petal_width <= 0.8\nmse = 3.092\nsamples = 150\nvalue = 3.759"] ; 4 | 1 [label="sepal_length <= 4.65\nmse = 0.03\nsamples = 50\nvalue = 1.464"] ; 5 | 0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ; 6 | 2 [label="sepal_width <= 3.5\nmse = 0.022\nsamples = 9\nvalue = 1.3"] ; 7 | 1 -> 2 ; 8 | 3 [label="petal_width <= 0.15\nmse = 0.012\nsamples = 8\nvalue = 1.338"] ; 9 | 2 -> 3 ; 10 | 4 [label="mse = 0.0\nsamples = 1\nvalue = 1.1"] ; 11 | 3 -> 4 ; 12 | 5 [label="mse = 0.005\nsamples = 7\nvalue = 1.371"] ; 13 | 3 -> 5 ; 14 | 6 [label="mse = 0.0\nsamples = 1\nvalue = 1.0"] ; 15 | 2 -> 6 ; 16 | 7 [label="sepal_length <= 5.75\nmse = 0.024\nsamples = 41\nvalue = 1.5"] ; 17 | 1 -> 7 ; 18 | 8 [label="petal_width <= 0.35\nmse = 0.022\nsamples = 40\nvalue = 1.508"] ; 19 | 7 -> 8 ; 20 | 9 [label="mse = 0.019\nsamples = 31\nvalue = 1.484"] ; 21 | 8 -> 9 ; 22 | 10 [label="mse = 0.025\nsamples = 9\nvalue = 1.589"] ; 23 | 8 -> 10 ; 24 | 11 [label="mse = -0.0\nsamples = 1\nvalue = 1.2"] ; 25 | 7 -> 11 ; 26 | 12 [label="petal_width <= 1.55\nmse = 0.675\nsamples = 100\nvalue = 4.906"] ; 27 | 0 -> 12 [labeldistance=2.5, labelangle=-45, headlabel="False"] ; 28 | 13 [label="sepal_length <= 5.95\nmse = 0.252\nsamples = 48\nvalue = 4.262"] ; 29 | 12 -> 13 ; 30 | 14 [label="sepal_length <= 5.15\nmse = 0.152\nsamples = 25\nvalue = 3.936"] ; 31 | 13 -> 14 ; 32 | 15 [label="mse = 0.032\nsamples = 4\nvalue = 3.275"] ; 33 | 14 -> 15 ; 34 | 16 [label="mse = 0.076\nsamples = 21\nvalue = 4.062"] ; 35 | 14 -> 16 ; 36 | 17 [label="petal_width <= 1.35\nmse = 0.118\nsamples = 23\nvalue = 4.617"] ; 37 | 13 -> 17 ; 38 | 18 [label="mse = 0.062\nsamples = 7\nvalue = 4.329"] ; 39 | 17 -> 18 ; 40 | 19 [label="mse = 0.09\nsamples = 16\nvalue = 4.744"] ; 41 | 17 -> 19 ; 42 | 20 [label="sepal_length <= 7.0\nmse = 0.33\nsamples = 52\nvalue = 5.5"] ; 43 | 12 -> 20 ; 44 | 21 [label="petal_width <= 2.05\nmse = 0.145\nsamples = 40\nvalue = 5.26"] ; 45 | 20 -> 21 ; 46 | 22 [label="mse = 0.102\nsamples = 23\nvalue = 5.052"] ; 47 | 21 -> 22 ; 48 | 23 [label="mse = 0.065\nsamples = 17\nvalue = 5.541"] ; 49 | 21 -> 23 ; 50 | 24 [label="sepal_length <= 7.5\nmse = 0.117\nsamples = 12\nvalue = 6.3"] ; 51 | 20 -> 24 ; 52 | 25 [label="mse = 0.026\nsamples = 6\nvalue = 6.033"] ; 53 | 24 -> 25 ; 54 | 26 [label="mse = 0.066\nsamples = 6\nvalue = 6.567"] ; 55 | 24 -> 26 ; 56 | } -------------------------------------------------------------------------------- /Aula 07.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Instituto Federal do Sudeste de Minas Gerais, Campus Barbacena\n", 8 | "### Projeto Laboratório de Redes de Conhecimento" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "## Curso de Mineração de Dados Aplicada\n", 16 | "\n", 17 | "Prof. Rafael José de Alencar Almeida\n", 18 | "\n", 19 | "\n", 20 | "
\n", 21 | "\n", 22 | "## Aula 7: Agrupamentos\n", 23 | "\n", 24 | "\n", 25 | "**Fonte da figura:** https://mubaris.com/posts/kmeans-clustering/" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | " " 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 1, 38 | "metadata": {}, 39 | "outputs": [ 40 | { 41 | "data": { 42 | "text/plain": [ 43 | "0 Campus Barbacena divulga Resultado Provisório ...\n", 44 | "1 Divulgado o Edital de convocação de assembleia...\n", 45 | "2 Pesquisador da Bélgica realiza palestra no Cam...\n", 46 | "3 Divulgada a homologação das inscrições à candi...\n", 47 | "4 Aprovado Regulamento de Eventos, Cerimonial e ...\n", 48 | "Name: doc, dtype: object" 49 | ] 50 | }, 51 | "execution_count": 1, 52 | "metadata": {}, 53 | "output_type": "execute_result" 54 | } 55 | ], 56 | "source": [ 57 | "import pandas as pd\n", 58 | "\n", 59 | "# Carrega o dataset de notícias do IF\n", 60 | "\n", 61 | "df = pd.read_csv('./data/df_noticias_if.csv')\n", 62 | "df['doc'] = df.apply(lambda row: row['titulo'] + ' ' + row['conteudo'], axis=1)\n", 63 | "df['doc'].head()" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 2, 69 | "metadata": {}, 70 | "outputs": [ 71 | { 72 | "data": { 73 | "text/plain": [ 74 | "0 campus divulga provisório viii barbacena provi...\n", 75 | "1 divulgado edital convocação assembleia centro ...\n", 76 | "2 pesquisador bélgica palestra campus luc fará p...\n", 77 | "3 divulgada homologação inscrições candidatura c...\n", 78 | "4 aprovado cerimonial protocolo if mg regulament...\n", 79 | "Name: doc, dtype: object" 80 | ] 81 | }, 82 | "execution_count": 2, 83 | "metadata": {}, 84 | "output_type": "execute_result" 85 | } 86 | ], 87 | "source": [ 88 | "import re\n", 89 | "import nltk\n", 90 | "from string import punctuation\n", 91 | "\n", 92 | "# Pré-processamento\n", 93 | "\n", 94 | "numbers = '0123456789'\n", 95 | "stopwords = nltk.corpus.stopwords.words('portuguese')\n", 96 | "\n", 97 | "def preprocessa(txt):\n", 98 | " txt = txt.lower()\n", 99 | " txt = ''.join([c for c in txt if c not in punctuation + numbers])\n", 100 | " txt = re.sub(r'\\n|\\r|\\t', '', txt)\n", 101 | " txt = re.sub(r' .+? ', ' ', txt)\n", 102 | " txt = ' '.join([t for t in txt.split(' ') if t not in stopwords])\n", 103 | " \n", 104 | " return txt\n", 105 | "\n", 106 | "df['doc'] = df['doc'].apply(preprocessa)\n", 107 | "df['doc'].head()" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": 3, 113 | "metadata": {}, 114 | "outputs": [ 115 | { 116 | "data": { 117 | "text/plain": [ 118 | "(1000, 3663)" 119 | ] 120 | }, 121 | "execution_count": 3, 122 | "metadata": {}, 123 | "output_type": "execute_result" 124 | } 125 | ], 126 | "source": [ 127 | "from sklearn.feature_extraction.text import TfidfVectorizer\n", 128 | "\n", 129 | "# Vetorização\n", 130 | "\n", 131 | "tfidf_vectorizer = TfidfVectorizer(\n", 132 | " min_df=2 # Frequência mínima\n", 133 | ")\n", 134 | "tfidf_matrix = tfidf_vectorizer.fit_transform(df['doc'])\n", 135 | "\n", 136 | "tfidf_matrix.shape" 137 | ] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "metadata": {}, 142 | "source": [ 143 | "## Clusterização\n", 144 | "\n", 145 | "Técnica de mineração de dados para agrupar dados automaticamente (aprendizado de máquina não-supervisionado), com base no seu grau de semelhança dos registros.\n", 146 | "\n", 147 | "### Algoritmo K-Means\n", 148 | "\n", 149 | "\n", 150 | "**Fonte da figura:** http://stanford.edu/~cpiech/cs221/handouts/kmeans.html" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 4, 156 | "metadata": {}, 157 | "outputs": [ 158 | { 159 | "data": { 160 | "text/plain": [ 161 | "KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=500,\n", 162 | " n_clusters=25, n_init=10, n_jobs=-1, precompute_distances='auto',\n", 163 | " random_state=1, tol=0.0001, verbose=0)" 164 | ] 165 | }, 166 | "execution_count": 4, 167 | "metadata": {}, 168 | "output_type": "execute_result" 169 | } 170 | ], 171 | "source": [ 172 | "from sklearn.cluster import KMeans\n", 173 | "\n", 174 | "N_CLUSTERS = 25\n", 175 | "\n", 176 | "kmeans = KMeans(\n", 177 | " n_clusters=N_CLUSTERS,\n", 178 | " max_iter=500,\n", 179 | " n_init=10,\n", 180 | " n_jobs=-1,\n", 181 | " random_state=1\n", 182 | ")\n", 183 | "\n", 184 | "kmeans.fit(tfidf_matrix)" 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": 5, 190 | "metadata": {}, 191 | "outputs": [], 192 | "source": [ 193 | "# Associa o id de cada cluster ao dataframe\n", 194 | "df['clusters'] = kmeans.labels_" 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "execution_count": 6, 200 | "metadata": {}, 201 | "outputs": [ 202 | { 203 | "data": { 204 | "text/plain": [ 205 | "array([20, 19, 10, 4, 20, 13, 12, 12, 20, 14, 20, 5, 15, 9, 4, 9, 0,\n", 206 | " 10, 10, 10, 4, 14, 0, 2, 10, 9, 9, 0, 20, 0, 9, 3, 5, 16,\n", 207 | " 3, 15, 16, 3, 15, 15, 3, 0, 10, 8, 20, 8, 15, 15, 15, 16],\n", 208 | " dtype=int32)" 209 | ] 210 | }, 211 | "execution_count": 6, 212 | "metadata": {}, 213 | "output_type": "execute_result" 214 | } 215 | ], 216 | "source": [ 217 | "# Exibe o cluster dos 50 primeiros documentos\n", 218 | "kmeans.labels_[:50]" 219 | ] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "execution_count": 7, 224 | "metadata": {}, 225 | "outputs": [ 226 | { 227 | "data": { 228 | "text/plain": [ 229 | "16 Estudante do Campus Barbacena ganha medalha de...\n", 230 | "22 Alunos do Campus Barbacena participam da cerim...\n", 231 | "27 Obap em Barbacena: Apresentações artísticas e ...\n", 232 | "29 Alunos do Curso Superior de Tecnologia em Sist...\n", 233 | "41 Alunos do Campus Barbacena participam do IV En...\n", 234 | "Name: titulo, dtype: object" 235 | ] 236 | }, 237 | "execution_count": 7, 238 | "metadata": {}, 239 | "output_type": "execute_result" 240 | } 241 | ], 242 | "source": [ 243 | "df[df['clusters'] == 0].head(5)['titulo']" 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": 8, 249 | "metadata": {}, 250 | "outputs": [ 251 | { 252 | "name": "stdout", 253 | "output_type": "stream", 254 | "text": [ 255 | "Cluster 1\n", 256 | "16 Estudante do Campus Barbacena ganha medalha de...\n", 257 | "22 Alunos do Campus Barbacena participam da cerim...\n", 258 | "27 Obap em Barbacena: Apresentações artísticas e ...\n", 259 | "Name: titulo, dtype: object\n", 260 | "\n", 261 | "----\n", 262 | "\n", 263 | "Cluster 2\n", 264 | "158 Atenção formandos dos Cursos de Nutrição e Li...\n", 265 | "704 Divulgada a homologação do resultado da eleiçã...\n", 266 | "705 Divulgada a homologação do resultado da eleiçã...\n", 267 | "Name: titulo, dtype: object\n", 268 | "\n", 269 | "----\n", 270 | "\n", 271 | "Cluster 3\n", 272 | "23 Cursos do Campus Barbacena recebem selo de qua...\n", 273 | "106 Novo Processo Seletivo - EaD - IF Sudeste MG\n", 274 | "121 Campus Barbacena reaproveita óleo usado \n", 275 | "Name: titulo, dtype: object\n", 276 | "\n", 277 | "----\n", 278 | "\n", 279 | "Cluster 4\n", 280 | "31 Divulgada a seleção para Monitor da disciplina...\n", 281 | "34 Divulgada a seleção de monitor para as discipl...\n", 282 | "37 Divulgada a seleção de monitores paras discipl...\n", 283 | "Name: titulo, dtype: object\n", 284 | "\n", 285 | "----\n", 286 | "\n", 287 | "Cluster 5\n", 288 | "3 Divulgada a homologação das inscrições à candi...\n", 289 | "14 Eleições CEPE: Homologação dos eleitos\n", 290 | "20 Eleições CEPE: Homologação do resultado das el...\n", 291 | "Name: titulo, dtype: object\n", 292 | "\n", 293 | "----\n", 294 | "\n", 295 | "Cluster 6\n", 296 | "11 Divulgada a palestra de abertura da semana aca...\n", 297 | "32 Eleições CEPE: Votação ocorrerá na próxima seg...\n", 298 | "59 Eleições CEPE: Diivulgada a ordem das chapas\n", 299 | "Name: titulo, dtype: object\n", 300 | "\n", 301 | "----\n", 302 | "\n", 303 | "Cluster 7\n", 304 | "117 Inscrições abertas para o VIII Simpósio de Pes...\n", 305 | "125 Projeto do Campus Barbacena recebe prêmio de d...\n", 306 | "188 Fecib movimenta Campus Barbacena com exposição...\n", 307 | "Name: titulo, dtype: object\n", 308 | "\n", 309 | "----\n", 310 | "\n", 311 | "Cluster 8\n", 312 | "279 VI Fecib: divulgado o resultado dos projetos s...\n", 313 | "301 Divulgado o resultado dos Projetos de Extensão...\n", 314 | "397 Pronatec - Campus Barbacena divulga resultado ...\n", 315 | "Name: titulo, dtype: object\n", 316 | "\n", 317 | "----\n", 318 | "\n", 319 | "Cluster 9\n", 320 | "43 Comunicado aposentadoria II\n", 321 | "45 Comunicado de aposentadoria\n", 322 | "65 COMUNICADO - comprar de ticktes para uso do re...\n", 323 | "Name: titulo, dtype: object\n", 324 | "\n", 325 | "----\n", 326 | "\n", 327 | "Cluster 10\n", 328 | "13 Participantes da 7ª OBAP visitam Museu Diaulas...\n", 329 | "15 Jogos dos Institutos Federais movimentam comun...\n", 330 | "25 Testes teóricos desafiam participantes da 7ª O...\n", 331 | "Name: titulo, dtype: object\n", 332 | "\n", 333 | "----\n", 334 | "\n", 335 | "Cluster 11\n", 336 | "2 Pesquisador da Bélgica realiza palestra no Cam...\n", 337 | "17 Atenção formandos: prova de beca e sessão foto...\n", 338 | "18 7ª Olimpíada Brasileira de Agropecuária propor...\n", 339 | "Name: titulo, dtype: object\n", 340 | "\n", 341 | "----\n", 342 | "\n", 343 | "Cluster 12\n", 344 | "64 Divulgado o Resultado provisório da seleção de...\n", 345 | "86 Divulgado o Processo Seletivo para bolsa de Ex...\n", 346 | "198 Divulgado o resultado da Eleição da Coordenaçã...\n", 347 | "Name: titulo, dtype: object\n", 348 | "\n", 349 | "----\n", 350 | "\n", 351 | "Cluster 13\n", 352 | "6 Campus Barbacena recebe professoras de Moçambique\n", 353 | "7 Estão abertas as inscrições para o Programa In...\n", 354 | "53 Projeto do Campus Barbacena forma novas equipe...\n", 355 | "Name: titulo, dtype: object\n", 356 | "\n", 357 | "----\n", 358 | "\n", 359 | "Cluster 14\n", 360 | "5 Atenção: aba para emissão de certificados\n", 361 | "95 Oferta de estágio para área de administração\n", 362 | "113 Laboratório de Solos do Campus Barbacena disp...\n", 363 | "Name: titulo, dtype: object\n", 364 | "\n", 365 | "----\n", 366 | "\n", 367 | "Cluster 15\n", 368 | "9 Aluno do Campus Barbacena ministra minicurso a...\n", 369 | "21 Professor do Campus Barbacena lança livro no X...\n", 370 | "66 Centro Acadêmico de Nutrição divulga carta de ...\n", 371 | "Name: titulo, dtype: object\n", 372 | "\n", 373 | "----\n", 374 | "\n", 375 | "Cluster 16\n", 376 | "12 Homologação dos resultados do EDITAL Nº 002, d...\n", 377 | "35 Atenção: bolsas de monitoria de física\n", 378 | "38 Divulgada a oportunidade de monitoria para o C...\n", 379 | "Name: titulo, dtype: object\n", 380 | "\n", 381 | "----\n", 382 | "\n", 383 | "Cluster 17\n", 384 | "33 Divulgada seleção para monitoria de atividades...\n", 385 | "36 Divulgada oportunidade de bolsa de monitoria p...\n", 386 | "49 Divulgada oportunidade de bolsa de monitoria p...\n", 387 | "Name: titulo, dtype: object\n", 388 | "\n", 389 | "----\n", 390 | "\n", 391 | "Cluster 18\n", 392 | "60 Divulgada a homologação do resultado da eleiçã...\n", 393 | "67 Divulgado o Resultado da apuração dos votos p...\n", 394 | "87 Divulgada a lista oficial de candidatos para c...\n", 395 | "Name: titulo, dtype: object\n", 396 | "\n", 397 | "----\n", 398 | "\n", 399 | "Cluster 19\n", 400 | "263 Divulgada a Retificação do Edital de Chamada P...\n", 401 | "308 Divulgada a retificação do Edital de Extensão ...\n", 402 | "360 Divulgada a retificação do Edital de Monitoria...\n", 403 | "Name: titulo, dtype: object\n", 404 | "\n", 405 | "----\n", 406 | "\n", 407 | "Cluster 20\n", 408 | "1 Divulgado o Edital de convocação de assembleia...\n", 409 | "69 Divulgado o Edital de convocação de eleição pa...\n", 410 | "74 Centro de Memória Diaulas Abreu do Campus Barb...\n", 411 | "Name: titulo, dtype: object\n", 412 | "\n", 413 | "----\n", 414 | "\n", 415 | "Cluster 21\n", 416 | "0 Campus Barbacena divulga Resultado Provisório ...\n", 417 | "4 Aprovado Regulamento de Eventos, Cerimonial e ...\n", 418 | "8 Diretoria de Pesquisa, Inovação e Pós-graduaçã...\n", 419 | "Name: titulo, dtype: object\n", 420 | "\n", 421 | "----\n", 422 | "\n", 423 | "Cluster 22\n", 424 | "94 Ello Consultoria Jr informa o resultado do pro...\n", 425 | "116 Ello Consultoria Jr publica retificação de Edital\n", 426 | "127 Ello Consultoria Jr lança edital de seleção de...\n", 427 | "Name: titulo, dtype: object\n", 428 | "\n", 429 | "----\n", 430 | "\n", 431 | "Cluster 23\n", 432 | "57 Divulgado o Resultado Final da Seleção do Sub...\n", 433 | "211 Divulgada a Classificação Final do Processo Se...\n", 434 | "220 Divulgado o Resultado Final da Homologação das...\n", 435 | "Name: titulo, dtype: object\n", 436 | "\n", 437 | "----\n", 438 | "\n", 439 | "Cluster 24\n", 440 | "102 Setor de Serviço Social divulga aviso\n", 441 | "111 Aviso do Setor de Serviço Social\n", 442 | "123 Aviso Setor de Serviço Social\n", 443 | "Name: titulo, dtype: object\n", 444 | "\n", 445 | "----\n", 446 | "\n", 447 | "Cluster 25\n", 448 | "130 Iférias realiza sorteio de vagas não ocupadas\n", 449 | "133 Colônia de férias: lista de espera\n", 450 | "143 XII IFérias: Divulgado o resultado do sorteio ...\n", 451 | "Name: titulo, dtype: object\n", 452 | "\n", 453 | "----\n", 454 | "\n" 455 | ] 456 | } 457 | ], 458 | "source": [ 459 | "# Exibe o título de 3 notícias de cada cluster\n", 460 | "for i in range(N_CLUSTERS):\n", 461 | " print('Cluster', i + 1)\n", 462 | " print(df[df['clusters'] == i].head(3)['titulo'])\n", 463 | " print('\\n----\\n')" 464 | ] 465 | }, 466 | { 467 | "cell_type": "markdown", 468 | "metadata": {}, 469 | "source": [ 470 | "## Comparação de algoritmos de clusterização\n", 471 | "\n", 472 | "https://scikit-learn.org/stable/modules/clustering.html#overview-of-clustering-methods\n", 473 | "\n", 474 | "" 475 | ] 476 | }, 477 | { 478 | "cell_type": "code", 479 | "execution_count": 9, 480 | "metadata": {}, 481 | "outputs": [ 482 | { 483 | "data": { 484 | "text/plain": [ 485 | "array([[0.00064169, 0. ],\n", 486 | " [0.00054253, 0.16098383],\n", 487 | " [0.0009236 , 0. ],\n", 488 | " ...,\n", 489 | " [0.00084651, 0.1051223 ],\n", 490 | " [0.00096439, 0.08247019],\n", 491 | " [0.00141705, 0. ]])" 492 | ] 493 | }, 494 | "execution_count": 9, 495 | "metadata": {}, 496 | "output_type": "execute_result" 497 | } 498 | ], 499 | "source": [ 500 | "from sklearn.cluster import FeatureAgglomeration\n", 501 | "\n", 502 | "fa = FeatureAgglomeration()\n", 503 | "fa.fit_transform(tfidf_matrix.toarray())" 504 | ] 505 | }, 506 | { 507 | "cell_type": "markdown", 508 | "metadata": {}, 509 | "source": [ 510 | "## Algoritmo Apriori\n", 511 | "\n", 512 | "\n", 513 | "\n", 514 | "**Fonte da figura:** https://edumine.wordpress.com/2013/09/11/apriori-algorithm-simplified-with-an-example/" 515 | ] 516 | }, 517 | { 518 | "cell_type": "code", 519 | "execution_count": 10, 520 | "metadata": {}, 521 | "outputs": [ 522 | { 523 | "data": { 524 | "text/html": [ 525 | "
\n", 526 | "\n", 539 | "\n", 540 | " \n", 541 | " \n", 542 | " \n", 543 | " \n", 544 | " \n", 545 | " \n", 546 | " \n", 547 | " \n", 548 | " \n", 549 | " \n", 550 | " \n", 551 | " \n", 552 | " \n", 553 | " \n", 554 | " \n", 555 | " \n", 556 | " \n", 557 | " \n", 558 | " \n", 559 | " \n", 560 | " \n", 561 | " \n", 562 | " \n", 563 | " \n", 564 | " \n", 565 | " \n", 566 | " \n", 567 | " \n", 568 | " \n", 569 | " \n", 570 | " \n", 571 | " \n", 572 | " \n", 573 | " \n", 574 | " \n", 575 | " \n", 576 | " \n", 577 | " \n", 578 | " \n", 579 | " \n", 580 | " \n", 581 | " \n", 582 | " \n", 583 | " \n", 584 | " \n", 585 | " \n", 586 | " \n", 587 | " \n", 588 | " \n", 589 | " \n", 590 | " \n", 591 | " \n", 592 | " \n", 593 | " \n", 594 | " \n", 595 | " \n", 596 | " \n", 597 | " \n", 598 | " \n", 599 | " \n", 600 | " \n", 601 | " \n", 602 | " \n", 603 | " \n", 604 | " \n", 605 | " \n", 606 | " \n", 607 | " \n", 608 | " \n", 609 | " \n", 610 | " \n", 611 | " \n", 612 | " \n", 613 | " \n", 614 | " \n", 615 | " \n", 616 | " \n", 617 | " \n", 618 | " \n", 619 | " \n", 620 | " \n", 621 | " \n", 622 | " \n", 623 | " \n", 624 | " \n", 625 | " \n", 626 | " \n", 627 | " \n", 628 | "
AppleCornDillEggsIce creamKidney BeansMilkNutmegOnionUnicornYogurt
0FalseFalseFalseTrueFalseTrueTrueTrueTrueFalseTrue
1FalseFalseTrueTrueFalseTrueFalseTrueTrueFalseTrue
2TrueFalseFalseTrueFalseTrueTrueFalseFalseFalseFalse
3FalseTrueFalseFalseFalseTrueTrueFalseFalseTrueTrue
4FalseTrueFalseTrueTrueTrueFalseFalseTrueFalseFalse
\n", 629 | "
" 630 | ], 631 | "text/plain": [ 632 | " Apple Corn Dill Eggs Ice cream Kidney Beans Milk Nutmeg Onion \\\n", 633 | "0 False False False True False True True True True \n", 634 | "1 False False True True False True False True True \n", 635 | "2 True False False True False True True False False \n", 636 | "3 False True False False False True True False False \n", 637 | "4 False True False True True True False False True \n", 638 | "\n", 639 | " Unicorn Yogurt \n", 640 | "0 False True \n", 641 | "1 False True \n", 642 | "2 False False \n", 643 | "3 True True \n", 644 | "4 False False " 645 | ] 646 | }, 647 | "execution_count": 10, 648 | "metadata": {}, 649 | "output_type": "execute_result" 650 | } 651 | ], 652 | "source": [ 653 | "from mlxtend.frequent_patterns import apriori\n", 654 | "from mlxtend.preprocessing import TransactionEncoder\n", 655 | "\n", 656 | "dataset = [\n", 657 | " ['Milk', 'Onion', 'Nutmeg', 'Kidney Beans', 'Eggs', 'Yogurt'],\n", 658 | " ['Dill', 'Onion', 'Nutmeg', 'Kidney Beans', 'Eggs', 'Yogurt'],\n", 659 | " ['Milk', 'Apple', 'Kidney Beans', 'Eggs'],\n", 660 | " ['Milk', 'Unicorn', 'Corn', 'Kidney Beans', 'Yogurt'],\n", 661 | " ['Corn', 'Onion', 'Onion', 'Kidney Beans', 'Ice cream', 'Eggs']\n", 662 | "]\n", 663 | "\n", 664 | "te = TransactionEncoder()\n", 665 | "te_ary = te.fit(dataset).transform(dataset)\n", 666 | "df = pd.DataFrame(te_ary, columns=te.columns_)\n", 667 | "df" 668 | ] 669 | }, 670 | { 671 | "cell_type": "code", 672 | "execution_count": 11, 673 | "metadata": {}, 674 | "outputs": [ 675 | { 676 | "data": { 677 | "text/html": [ 678 | "
\n", 679 | "\n", 692 | "\n", 693 | " \n", 694 | " \n", 695 | " \n", 696 | " \n", 697 | " \n", 698 | " \n", 699 | " \n", 700 | " \n", 701 | " \n", 702 | " \n", 703 | " \n", 704 | " \n", 705 | " \n", 706 | " \n", 707 | " \n", 708 | " \n", 709 | " \n", 710 | " \n", 711 | " \n", 712 | " \n", 713 | " \n", 714 | " \n", 715 | " \n", 716 | " \n", 717 | " \n", 718 | " \n", 719 | " \n", 720 | " \n", 721 | " \n", 722 | " \n", 723 | " \n", 724 | " \n", 725 | " \n", 726 | " \n", 727 | " \n", 728 | " \n", 729 | " \n", 730 | " \n", 731 | " \n", 732 | " \n", 733 | " \n", 734 | " \n", 735 | " \n", 736 | " \n", 737 | " \n", 738 | " \n", 739 | " \n", 740 | " \n", 741 | " \n", 742 | " \n", 743 | " \n", 744 | " \n", 745 | " \n", 746 | " \n", 747 | " \n", 748 | " \n", 749 | " \n", 750 | " \n", 751 | " \n", 752 | " \n", 753 | " \n", 754 | " \n", 755 | " \n", 756 | " \n", 757 | "
supportitemsets
00.8(3)
11.0(5)
20.6(6)
30.6(8)
40.6(10)
50.8(3, 5)
60.6(8, 3)
70.6(5, 6)
80.6(8, 5)
90.6(10, 5)
100.6(8, 3, 5)
\n", 758 | "
" 759 | ], 760 | "text/plain": [ 761 | " support itemsets\n", 762 | "0 0.8 (3)\n", 763 | "1 1.0 (5)\n", 764 | "2 0.6 (6)\n", 765 | "3 0.6 (8)\n", 766 | "4 0.6 (10)\n", 767 | "5 0.8 (3, 5)\n", 768 | "6 0.6 (8, 3)\n", 769 | "7 0.6 (5, 6)\n", 770 | "8 0.6 (8, 5)\n", 771 | "9 0.6 (10, 5)\n", 772 | "10 0.6 (8, 3, 5)" 773 | ] 774 | }, 775 | "execution_count": 11, 776 | "metadata": {}, 777 | "output_type": "execute_result" 778 | } 779 | ], 780 | "source": [ 781 | "apriori(df, min_support=0.6)" 782 | ] 783 | }, 784 | { 785 | "cell_type": "code", 786 | "execution_count": 12, 787 | "metadata": {}, 788 | "outputs": [ 789 | { 790 | "data": { 791 | "text/html": [ 792 | "
\n", 793 | "\n", 806 | "\n", 807 | " \n", 808 | " \n", 809 | " \n", 810 | " \n", 811 | " \n", 812 | " \n", 813 | " \n", 814 | " \n", 815 | " \n", 816 | " \n", 817 | " \n", 818 | " \n", 819 | " \n", 820 | " \n", 821 | " \n", 822 | " \n", 823 | " \n", 824 | " \n", 825 | " \n", 826 | " \n", 827 | " \n", 828 | " \n", 829 | " \n", 830 | " \n", 831 | " \n", 832 | " \n", 833 | " \n", 834 | " \n", 835 | " \n", 836 | " \n", 837 | " \n", 838 | " \n", 839 | " \n", 840 | " \n", 841 | " \n", 842 | " \n", 843 | " \n", 844 | " \n", 845 | " \n", 846 | " \n", 847 | " \n", 848 | " \n", 849 | " \n", 850 | " \n", 851 | " \n", 852 | " \n", 853 | " \n", 854 | " \n", 855 | " \n", 856 | " \n", 857 | " \n", 858 | " \n", 859 | " \n", 860 | " \n", 861 | " \n", 862 | " \n", 863 | " \n", 864 | " \n", 865 | " \n", 866 | " \n", 867 | " \n", 868 | " \n", 869 | " \n", 870 | " \n", 871 | "
supportitemsets
00.8(Eggs)
11.0(Kidney Beans)
20.6(Milk)
30.6(Onion)
40.6(Yogurt)
50.8(Kidney Beans, Eggs)
60.6(Onion, Eggs)
70.6(Milk, Kidney Beans)
80.6(Kidney Beans, Onion)
90.6(Kidney Beans, Yogurt)
100.6(Kidney Beans, Onion, Eggs)
\n", 872 | "
" 873 | ], 874 | "text/plain": [ 875 | " support itemsets\n", 876 | "0 0.8 (Eggs)\n", 877 | "1 1.0 (Kidney Beans)\n", 878 | "2 0.6 (Milk)\n", 879 | "3 0.6 (Onion)\n", 880 | "4 0.6 (Yogurt)\n", 881 | "5 0.8 (Kidney Beans, Eggs)\n", 882 | "6 0.6 (Onion, Eggs)\n", 883 | "7 0.6 (Milk, Kidney Beans)\n", 884 | "8 0.6 (Kidney Beans, Onion)\n", 885 | "9 0.6 (Kidney Beans, Yogurt)\n", 886 | "10 0.6 (Kidney Beans, Onion, Eggs)" 887 | ] 888 | }, 889 | "execution_count": 12, 890 | "metadata": {}, 891 | "output_type": "execute_result" 892 | } 893 | ], 894 | "source": [ 895 | "# Exibindo o nome dos itens (colunas)\n", 896 | "apriori(df, min_support=0.6, use_colnames=True)" 897 | ] 898 | }, 899 | { 900 | "cell_type": "markdown", 901 | "metadata": {}, 902 | "source": [ 903 | "## Atividade para casa\n", 904 | "\n", 905 | "Implemente a técnica de modelagem de tópicos utilizando clusterização. \n", 906 | "\n", 907 | "O usuário deverá informar o número de assuntos, e o programa deverá retornar os 5 termos e os 5 documentos mais relevantes para cada assunto.\n", 908 | "\n", 909 | "O desafio consiste no emprego de uma métrica para definir os documentos e os termos mais relevantes de cada cluster." 910 | ] 911 | } 912 | ], 913 | "metadata": { 914 | "kernelspec": { 915 | "display_name": "Python 3", 916 | "language": "python", 917 | "name": "python3" 918 | }, 919 | "language_info": { 920 | "codemirror_mode": { 921 | "name": "ipython", 922 | "version": 3 923 | }, 924 | "file_extension": ".py", 925 | "mimetype": "text/x-python", 926 | "name": "python", 927 | "nbconvert_exporter": "python", 928 | "pygments_lexer": "ipython3", 929 | "version": "3.6.4" 930 | } 931 | }, 932 | "nbformat": 4, 933 | "nbformat_minor": 2 934 | } 935 | -------------------------------------------------------------------------------- /.ipynb_checkpoints/Processamento de linguagem natural e mineração de dados textuais-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Dataset notícias IF Barbacena" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 2, 13 | "metadata": {}, 14 | "outputs": [ 15 | { 16 | "name": "stdout", 17 | "output_type": "stream", 18 | "text": [ 19 | "1000\n", 20 | "\n", 21 | "\n", 22 | "\tO Campus Barbacena divulgou o Resultado Provisório do VIII Simpósio de Pesquisa e Inovação.\n", 23 | "\n", 24 | "\tOs estudantes devem ficar atentos as observações que constam no final do documento.\n", 25 | "\n", 26 | "Leia o documento\n", 27 | "\n" 28 | ] 29 | } 30 | ], 31 | "source": [ 32 | "import json\n", 33 | "\n", 34 | "noticias = json.load(open('noticias_if.json'))\n", 35 | "\n", 36 | "print(len(noticias))\n", 37 | "\n", 38 | "n1 = noticias[0]\n", 39 | "\n", 40 | "print(n1['conteudo'])" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "## Normalização do texto\n", 48 | "\n", 49 | "- Remoção de acentos\n", 50 | "- Remoção de quebras de linha e tabulação\n", 51 | "- Conversão para minúsculas\n", 52 | "- Remoção de espaços duplicados" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": 7, 58 | "metadata": {}, 59 | "outputs": [ 60 | { 61 | "name": "stdout", 62 | "output_type": "stream", 63 | "text": [ 64 | "o campus barbacena divulgou o resultado provisorio do viii simposio de pesquisa e inovacao. os estudantes devem ficar atentos as observacoes que constam no final do documento. leia o documento\n" 65 | ] 66 | } 67 | ], 68 | "source": [ 69 | "import re\n", 70 | "from unicodedata import normalize\n", 71 | "\n", 72 | "def normaliza(txt): \n", 73 | " txt = normalize('NFKD', txt).encode('ASCII','ignore').decode('ASCII')\n", 74 | " \n", 75 | " txt = re.sub(r'\\t|\\n|\\r', ' ', txt)\n", 76 | " \n", 77 | " txt = txt.lower()\n", 78 | " \n", 79 | " txt = re.sub(r' +', ' ', txt).strip()\n", 80 | " \n", 81 | " return txt\n", 82 | "\n", 83 | "n1 = normaliza(noticias[0]['conteudo'])\n", 84 | "\n", 85 | "print(n1)" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": {}, 91 | "source": [ 92 | "## Tokenização" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": 8, 98 | "metadata": {}, 99 | "outputs": [ 100 | { 101 | "name": "stdout", 102 | "output_type": "stream", 103 | "text": [ 104 | "['o', 'campus', 'barbacena', 'divulgou', 'o', 'resultado', 'provisorio', 'do', 'viii', 'simposio', 'de', 'pesquisa', 'e', 'inovacao', 'os', 'estudantes', 'devem', 'ficar', 'atentos', 'as', 'observacoes', 'que', 'constam', 'no', 'final', 'do', 'documento', 'leia', 'o', 'documento']\n" 105 | ] 106 | } 107 | ], 108 | "source": [ 109 | "from nltk import word_tokenize\n", 110 | "from string import punctuation \n", 111 | "\n", 112 | "# Tokeniza\n", 113 | "tokens = word_tokenize(n1)\n", 114 | "\n", 115 | "# Remove pontuação\n", 116 | "tokens_sem_pontuacao = [t for t in tokens if t not in punctuation]\n", 117 | "print(tokens_sem_pontuacao)" 118 | ] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "metadata": {}, 123 | "source": [ 124 | "## Remoção de stop words" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": 9, 130 | "metadata": {}, 131 | "outputs": [ 132 | { 133 | "name": "stdout", 134 | "output_type": "stream", 135 | "text": [ 136 | "15 stopwords pt: ['de', 'a', 'o', 'que', 'e', 'do', 'da', 'em', 'um', 'para', 'com', 'não', 'uma', 'os', 'no'] \n", 137 | "\n", 138 | "['campus', 'barbacena', 'divulgou', 'resultado', 'provisorio', 'viii', 'simposio', 'pesquisa', 'inovacao', 'estudantes', 'devem', 'ficar', 'atentos', 'observacoes', 'constam', 'final', 'documento', 'leia', 'documento']\n" 139 | ] 140 | } 141 | ], 142 | "source": [ 143 | "import nltk\n", 144 | "\n", 145 | "stopwords = nltk.corpus.stopwords.words('portuguese')\n", 146 | "\n", 147 | "print('15 stopwords pt:', stopwords[:15], '\\n')\n", 148 | "\n", 149 | "tokens = [t for t in tokens_sem_pontuacao if t not in stopwords]\n", 150 | "\n", 151 | "print(tokens)" 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": {}, 157 | "source": [ 158 | "## Stemming" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": 10, 164 | "metadata": {}, 165 | "outputs": [ 166 | { 167 | "name": "stdout", 168 | "output_type": "stream", 169 | "text": [ 170 | "program\n", 171 | "program\n", 172 | "program\n", 173 | "----------\n", 174 | "['campu', 'barbacen', 'divulg', 'result', 'provisori', 'vii', 'simposi', 'pesquis', 'inovaca', 'estud', 'dev', 'fic', 'atent', 'observaco', 'const', 'final', 'document', 'lei', 'document']\n" 175 | ] 176 | } 177 | ], 178 | "source": [ 179 | "stemmer = nltk.stem.RSLPStemmer()\n", 180 | "\n", 181 | "print(stemmer.stem('programar'))\n", 182 | "print(stemmer.stem('programava'))\n", 183 | "print(stemmer.stem('programaremos'))\n", 184 | "\n", 185 | "tokens = [stemmer.stem(t) for t in tokens]\n", 186 | "print('----------')\n", 187 | "print(tokens[:100])" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "## Vectorization (TF-IDF)" 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "execution_count": 11, 200 | "metadata": {}, 201 | "outputs": [ 202 | { 203 | "name": "stdout", 204 | "output_type": "stream", 205 | "text": [ 206 | "(1000, 11575)\n", 207 | "['entenda', 'entende', 'entendem', 'entendendo', 'entender', 'entendimento', 'enterro', 'entidades', 'entomologia', 'entorno', 'entrada', 'entram', 'entrando', 'entrar', 'entraram', 'entraremos', 'entrega', 'entregando', 'entregar', 'entregou', 'entregue', 'entregues', 'entretanto', 'entretenimento', 'entrevista', 'entrevistados', 'entrevistas', 'entrou', 'entusiasmados', 'entusiasmo', 'envergadura', 'envia', 'enviada', 'enviadas', 'enviado', 'enviados', 'enviando', 'enviar', 'enviara', 'enviaria', 'envie', 'envio', 'environmental', 'envolve', 'envolvem', 'envolvendo', 'envolver', 'envolveram', 'envolveu', 'envolviam']\n" 208 | ] 209 | } 210 | ], 211 | "source": [ 212 | "from sklearn.feature_extraction.text import TfidfVectorizer\n", 213 | "\n", 214 | "lista_noticias = [n['conteudo'] for n in noticias]\n", 215 | "\n", 216 | "lista_noticias_preproc = []\n", 217 | "\n", 218 | "# Preprocessa as notícias\n", 219 | "for i, noticia in enumerate(lista_noticias):\n", 220 | " norm = normaliza(noticia)\n", 221 | " tokens = [t for t in word_tokenize(norm) if (t not in punctuation and t not in stopwords)]\n", 222 | " noticia_preproc = ' '.join(tokens)\n", 223 | " \n", 224 | " # Adiciona o id da notícia (índice)\n", 225 | " lista_noticias_preproc.append(str(i) + '\\n' + noticia_preproc)\n", 226 | "\n", 227 | "tfidf_vectorizer = TfidfVectorizer(analyzer='word')\n", 228 | "\n", 229 | "tfidf_matrix = tfidf_vectorizer.fit_transform(lista_noticias_preproc)\n", 230 | "\n", 231 | "print(tfidf_matrix.shape)\n", 232 | "print(tfidf_vectorizer.get_feature_names()[5000:5050])" 233 | ] 234 | }, 235 | { 236 | "cell_type": "markdown", 237 | "metadata": {}, 238 | "source": [ 239 | "## Similaridade textual" 240 | ] 241 | }, 242 | { 243 | "cell_type": "code", 244 | "execution_count": 12, 245 | "metadata": {}, 246 | "outputs": [ 247 | { 248 | "name": "stdout", 249 | "output_type": "stream", 250 | "text": [ 251 | "(1000, 1000) \n", 252 | "\n", 253 | "CPU times: user 32 ms, sys: 8 ms, total: 40 ms\n", 254 | "Wall time: 38.8 ms\n" 255 | ] 256 | } 257 | ], 258 | "source": [ 259 | "%%time\n", 260 | "\n", 261 | "from sklearn.metrics.pairwise import cosine_similarity\n", 262 | "\n", 263 | "'''\n", 264 | " Distância cosine_similarity\n", 265 | " Valor 1 -> documentos iguais\n", 266 | " \n", 267 | " Similaridade:\n", 268 | " Valor 0 -> documentos iguais\n", 269 | "'''\n", 270 | "\n", 271 | "# Precomputa todas as distâncias\n", 272 | "dist = 1 - cosine_similarity(tfidf_matrix)\n", 273 | "\n", 274 | "print(dist.shape, '\\n')" 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": 13, 280 | "metadata": {}, 281 | "outputs": [ 282 | { 283 | "name": "stdout", 284 | "output_type": "stream", 285 | "text": [ 286 | "(1000, 1000) \n", 287 | "\n", 288 | "[ -2.22044605e-16 8.73339844e-01 1.00000000e+00 1.00000000e+00\n", 289 | " 9.37683359e-01 9.57493308e-01 9.60413006e-01 9.55252975e-01\n", 290 | " 7.72281511e-01 9.70043880e-01] \n", 291 | "\n", 292 | "0.995450947468 \n", 293 | "\n" 294 | ] 295 | } 296 | ], 297 | "source": [ 298 | "print(dist.shape, '\\n')\n", 299 | "\n", 300 | "print(dist[0][:10], '\\n')\n", 301 | "\n", 302 | "print(dist[0][500], '\\n')" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 14, 308 | "metadata": {}, 309 | "outputs": [ 310 | { 311 | "name": "stdout", 312 | "output_type": "stream", 313 | "text": [ 314 | "D1: Estão abertas as inscrições para Festival de Dança do IF Sudeste de Minas Gerais - Campus Barbacena “Volta ao Mundo” \n", 315 | "\n", 316 | "D2: Abertura de ciclo de palestras sobre conservação da natureza é um sucesso \n", 317 | "\n", 318 | "D3: Campus Barbacena divulga edital do Festival de Dança “Hollywood Ifest” \n", 319 | "\n", 320 | "D1 -> D3 0.282603948493\n", 321 | "D2 -> D3 0.96451245341\n" 322 | ] 323 | } 324 | ], 325 | "source": [ 326 | "print('D1:', noticias[847]['titulo'], '\\n')\n", 327 | "print('D2:', noticias[326]['titulo'], '\\n')\n", 328 | "print('D3:', noticias[338]['titulo'], '\\n')\n", 329 | "\n", 330 | "print('D1 -> D3', dist[847][338])\n", 331 | "print('D2 -> D3', dist[326][338])" 332 | ] 333 | }, 334 | { 335 | "cell_type": "markdown", 336 | "metadata": {}, 337 | "source": [ 338 | "## Clusterização de documentos textuais" 339 | ] 340 | }, 341 | { 342 | "cell_type": "code", 343 | "execution_count": 27, 344 | "metadata": {}, 345 | "outputs": [ 346 | { 347 | "data": { 348 | "text/plain": [ 349 | "array([44, 46, 42, 31, 38, 41, 34, 24, 48, 35, 34, 42, 37, 33, 31, 17, 17,\n", 350 | " 1, 33, 10, 39, 16, 1, 8, 42, 33, 33, 33, 44, 48, 23, 24, 27, 37,\n", 351 | " 5, 5, 5, 21, 5, 37, 5, 0, 7, 13, 23, 13, 5, 37, 5, 21, 5,\n", 352 | " 37, 5, 1, 5, 5, 5, 37, 11, 45, 39, 11, 12, 1, 14, 16, 1, 39,\n", 353 | " 34, 10, 45, 7, 1, 49, 16, 44, 29, 45, 34, 24, 1, 10, 1, 29, 49,\n", 354 | " 2, 28, 39, 24, 24, 17, 45, 46, 39, 36, 4, 46, 16, 39, 16], dtype=int32)" 355 | ] 356 | }, 357 | "execution_count": 27, 358 | "metadata": {}, 359 | "output_type": "execute_result" 360 | } 361 | ], 362 | "source": [ 363 | "from sklearn.cluster import KMeans\n", 364 | "\n", 365 | "clusters = 50\n", 366 | "model = KMeans(n_clusters=clusters, init='k-means++', max_iter=100, n_init=1)\n", 367 | "model.fit(tfidf_matrix)\n", 368 | "\n", 369 | "# Vetor com o identificador do cluster dos 100 primeiros documentos\n", 370 | "model.labels_[:100]" 371 | ] 372 | }, 373 | { 374 | "cell_type": "markdown", 375 | "metadata": {}, 376 | "source": [ 377 | "## Topic modeling" 378 | ] 379 | }, 380 | { 381 | "cell_type": "code", 382 | "execution_count": 29, 383 | "metadata": {}, 384 | "outputs": [ 385 | { 386 | "name": "stdout", 387 | "output_type": "stream", 388 | "text": [ 389 | "Matriz W: (1000, 25)\n", 390 | "Matriz H: (25, 11575) \n", 391 | "\n" 392 | ] 393 | } 394 | ], 395 | "source": [ 396 | "from sklearn.decomposition import NMF\n", 397 | "\n", 398 | "tfidf_feature_names = tfidf_vectorizer.get_feature_names()\n", 399 | "\n", 400 | "# Número de tópicos\n", 401 | "num_topics = 25\n", 402 | "\n", 403 | "# Fatoração da Matriz Não-Negativa (NMF)\n", 404 | "nmf_model = NMF(\n", 405 | " n_components=num_topics,\n", 406 | " random_state=1, alpha=.1, l1_ratio=.5, init='nndsvd'\n", 407 | ").fit(tfidf_matrix)\n", 408 | "\n", 409 | "# Matriz de tópicos x documentos (W)\n", 410 | "nmf_W = nmf_model.transform(tfidf_matrix)\n", 411 | "\n", 412 | "# Matriz de paralvras x tópicos (H)\n", 413 | "nmf_H = nmf_model.components_\n", 414 | "\n", 415 | "# Dimensão das matrizes resultantes\n", 416 | "print('Matriz W:', nmf_W.shape)\n", 417 | "print('Matriz H:', nmf_H.shape, '\\n')" 418 | ] 419 | }, 420 | { 421 | "cell_type": "code", 422 | "execution_count": 111, 423 | "metadata": {}, 424 | "outputs": [ 425 | { 426 | "name": "stdout", 427 | "output_type": "stream", 428 | "text": [ 429 | "\n", 430 | "Tópico 1\n", 431 | " Principais termos: barbacena (0.66), campus (0.63), curso (0.38), alunos (0.37), dia (0.35)\n", 432 | " Principais notícias relacionadas ao tópico:\n", 433 | "\t- Campus Barbacena monta Fazendinha Pedagógica na 49ª Exposição de Barbacena (0.15)\n", 434 | "\t- Campus Barbacena é destaque na 49ª Exposição Agropecuária de Barbacena (0.15)\n", 435 | "\t- Prorrogadas as inscrições para o Curso de Esgrima (0.14)\n", 436 | "\t- Mensagem do Diretor-geral (0.14)\n", 437 | "\t- Atenção Estudantes do Curso de Licenciatura em Educação Física: Estão abertas as inscrições para o Curso de Conhecimentos Básicos de Esgrima (Florete, Sábre e Espada) (0.14)\n", 438 | "\n", 439 | "Tópico 2\n", 440 | " Principais termos: resultado (1.97), veja (0.83), divulgado (0.81), final (0.48), provisorio (0.37)\n", 441 | " Principais notícias relacionadas ao tópico:\n", 442 | "\t- Divulgado o resultado dos Projetos de Extensão 2017 (0.25)\n", 443 | "\t- Divulgado o Resultado provisório da seleção de projetos de monitoria - Edital Nº 02/2017 (0.24)\n", 444 | "\t- Divulgado o Resultado Final do Edital PIBID 01 - 2016 (0.23)\n", 445 | "\t- Edital de Vagas Remanescentes: Divulgado o Resultado da Análise Curricular e o Resultado Provisório (0.22)\n", 446 | "\t- Pronatec: Divulgado o Resultado Final do Edital Nº 031/2016 (0.21)\n", 447 | "\n", 448 | "Tópico 3\n", 449 | " Principais termos: licenciatura (1.1), biologicas (0.48), ciencias (0.44), bacharelado (0.42), sistemas (0.42)\n", 450 | " Principais notícias relacionadas ao tópico:\n", 451 | "\t- Divulgado os inscritos para eleição de discentes para compor os colegiados dos cursos superiores (0.43)\n", 452 | "\t- Divulgado o resultado da eleição dos discentes para compor os colegiados dos cursos superiores (Bacharelado em Nutrição; Licenciatura em Ciências Biológicas; Licenciatura em Educação Física; Licenciatura em Química; Tecnologia em Sistemas para Internet) (0.43)\n", 453 | "\t- Divulgado o resultado da eleição dos docentes para compor os colegiados dos cursos superiores (Bacharelado em Nutrição; Licenciatura em Ciências Biológicas; Licenciatura em Educação Física; Licenciatura em Química; Tecnologia em Sistemas para Internet (0.43)\n", 454 | "\t- Divulgada a homologação do resultado da eleição dos docentes para compor os colegiados dos cursos superiores (Bacharelado em Nutrição; Licenciatura em Ciências Biológicas; Licenciatura em Educação Física; Licenciatura em Química; Tecnologia em Sistemas (0.41)\n", 455 | "\t- Divulgada a homologação do resultado da eleição dos discentes para compor os colegiados dos cursos superiores (Bacharelado em Nutrição; Licenciatura em Ciências Biológicas; Licenciatura em Educação Física; Licenciatura em Química; Tecnologia em Sistemas (0.4)\n", 456 | "\n", 457 | "Tópico 4\n", 458 | " Principais termos: remunerado (0.81), retificacao (0.8), 8641 (0.75), estagio (0.74), programa (0.51)\n", 459 | " Principais notícias relacionadas ao tópico:\n", 460 | "\t- Divulgada a II Retificação do Programa de Estágio Remunerado (0.38)\n", 461 | "\t- Divulgada a retificação do Edital do Programa de Estágio Remunerado (0.38)\n", 462 | "\t- Programa de Estágio Remunerado: Divulgada a retificação do resultado da análise de currículo (0.37)\n", 463 | "\t- Programa de Estágio Remunerado: Divulgada a retificação do resultado das entrevistas (0.37)\n", 464 | "\t- Divulgada a retificação do Edital do Programa de Estágio Remunerado (0.36)\n", 465 | "\n", 466 | "Tópico 5\n", 467 | " Principais termos: academico (0.88), centro (0.82), convocacao (0.76), assembleia (0.52), divulgado (0.48)\n", 468 | " Principais notícias relacionadas ao tópico:\n", 469 | "\t- Divulgado o Edital de convocação de assembleia do Centro Acadêmico de Nutrição (0.45)\n", 470 | "\t- Divulgado o Edital de convocação de assembleia geral do Centro Acadêmico em Nutrição – C.A.N (0.4)\n", 471 | "\t- Divulgado o Edital de Convocação da Assembleia Geral do Centro Acadêmico de Bacharelado em Nutrição – C.A.B.N. (0.37)\n", 472 | "\t- Divulgado o Edital de Convocação da Assembleia Geral do Centro Acadêmico de Licenciatura em Química - C.A.L.Q. (0.37)\n", 473 | "\t- Atenção: Divulgado o Edital de convocação da assembleia geral do Centro Acadêmico de Licenciatura em Química C.A.L.Q. (0.37)\n", 474 | "\n", 475 | "Tópico 6\n", 476 | " Principais termos: 00 (0.57), etaria (0.47), faixa (0.47), anos (0.3), 11 (0.26)\n", 477 | " Principais notícias relacionadas ao tópico:\n", 478 | "\t- Estão abertas as inscrições para o X IFérias – Colônia de Férias do Campus Barbacena (0.67)\n", 479 | "\t- Inscrições para a X Colônia de Férias começam na próxima segunda-feira (0.66)\n", 480 | "\t- Divulgado o Edital do X IFérias (Colônia de Férias do Campus Barbacena) (0.66)\n", 481 | "\t- Divulgado o Edital do XI IFérias (Colônia de Férias do Campus Barbacena) (0.61)\n", 482 | "\t- Divulgado o Edital do XII IFérias (Colônia de Férias do Campus Barbacena) (0.52)\n", 483 | "\n", 484 | "Tópico 7\n", 485 | " Principais termos: monitoria (0.68), prova (0.35), alunos (0.31), fisica (0.26), selecao (0.24)\n", 486 | " Principais notícias relacionadas ao tópico:\n", 487 | "\t- Divulgação de monitoria de Física do 3º ano do ensino médio para candidatos matriculados no 3º ano de qualquer curso técnico do IF - Barbacena. (0.55)\n", 488 | "\t- Divulgação de monitoria de Física Instrumental (0.53)\n", 489 | "\t- Divulgação de monitoria de Física para candidatos das licenciaturas dos cursos superiores do IF - Barbacena (0.53)\n", 490 | "\t- Divulgada oportunidade de monitoria de Física para candidatos das licenciaturas dos cursos superiores do Campus Barbacena (0.51)\n", 491 | "\t- Atenção alunos dos Cursos Técnicos Integrados ao Ensino Médio (3ºano): divulgada a oportunidade de vaga para monitoria de Física (0.5)\n", 492 | "\n", 493 | "Tópico 8\n", 494 | " Principais termos: escolha (0.56), representantes (0.42), conselho (0.4), docentes (0.39), eleitoral (0.36)\n", 495 | " Principais notícias relacionadas ao tópico:\n", 496 | "\t- Divulgado o Resultado dos inscritos para escolha dos representantes dos servidores docentes, técnicos - administrativos em educação e discentes do CONSU e CEPE do Campus Barbacena (0.48)\n", 497 | "\t- Divulgada a Convocação eleitoral para escolha dos representantes dos servidores docentes, técnico-administrativos e discentes do Conselho de Ensino, Pesquisa e Extensão (CEPE) do Campus Barbacena (0.48)\n", 498 | "\t- Eleições CEPE: Divulgados os inscritos (0.46)\n", 499 | "\t- Divulgada a Homologação dos inscritos para escolha dos representantes dos servidores docentes, técnicos - administrativos em educação e discentes do CONSU e CEPE (0.45)\n", 500 | "\t- Divulgada a Homologação dos eleitos no processo eleitoral para escolha dos membros do Conselho Superior (CONSU) e Conselho de Ensino, Pesquisa e Extensão (CEPE) do IF Sudeste MG – Campus Barbacena (0.38)\n", 501 | "\n", 502 | "Tópico 9\n", 503 | " Principais termos: pesquisa (0.69), inovacao (0.42), iniciacao (0.36), viii (0.33), cientifica (0.3)\n", 504 | " Principais notícias relacionadas ao tópico:\n", 505 | "\t- Publicados resultados provisórios de seleção dos projetos de pesquisa submetidos ao VIII Programa de iniciação científica IF Sudeste MG / CNPq (2017/2018) (0.53)\n", 506 | "\t- Publicado resultado consolidado dos projetos de pesquisa submetidos ao VIII Programa de iniciação científica IF Sudeste MG / CNPq (2017/2018) (0.53)\n", 507 | "\t- Publicados resultados provisórios de seleção dos projetos de pesquisa FAPEMIG editais 10/2015 e 11/2015 (0.41)\n", 508 | "\t- Publicado edital de chamada de projetos para o VIII Programa Institucional de Bolsas de Iniciação Científica – Fapemig/IFSudesteMG (0.38)\n", 509 | "\t- Publicado resultado consolidado com distribuição de bolsas dos projetos de pesquisa submetidos aos editais 10/2016 e 11/2016 - FAPEMIG/IF Sudeste MG (0.37)\n", 510 | "\n", 511 | "Tópico 10\n", 512 | " Principais termos: vagas (0.72), seletivo (0.54), remanescentes (0.5), processo (0.45), preenchimento (0.38)\n", 513 | " Principais notícias relacionadas ao tópico:\n", 514 | "\t- Divulgada a homologação das inscrições do Processo Seletivo para Preenchimento de Vagas Remanescentes 2/2017 (0.42)\n", 515 | "\t- Divulgado o Resultado Final da Homologação das Inscrições do Processo Seletivo para Preenchimento de Vagas Remanescentes (0.4)\n", 516 | "\t- Divulgada a Classificação Final do Processo Seletivo para Preenchimento de Vagas Remanescentes, referente ao Edital 10/2017 (0.36)\n", 517 | "\t- Divulgado o resultado final do Processo Seletivo para preenchimento das vagas remanescentes nos cursos de graduação (0.34)\n", 518 | "\t- IF Sudeste MG divulga datas do Processo Seletivo para o segundo semestre de 2017 (0.32)\n", 519 | "\n", 520 | "Tópico 11\n", 521 | " Principais termos: danca (0.49), festival (0.38), grupos (0.2), barbacena (0.18), serao (0.15)\n", 522 | " Principais notícias relacionadas ao tópico:\n", 523 | "\t- Campus Barbacena promove Festival de Dança \"Volta ao Mundo” (0.77)\n", 524 | "\t- Estão abertas as inscrições para Festival de Dança do IF Sudeste de Minas Gerais - Campus Barbacena “Volta ao Mundo” (0.77)\n", 525 | "\t- Prorrogadas as inscrições para Festival de Dança do Campus Barbacena - “Volta ao Mundo” (0.76)\n", 526 | "\t- Estudantes participam da \"Oficina de Dança Folclórica na Escola\" (0.76)\n", 527 | "\t- Campus Barbacena divulga edital do Festival de Dança “Hollywood Ifest” (0.69)\n", 528 | "\n", 529 | "Tópico 12\n", 530 | " Principais termos: 8613 (0.47), matriculas (0.44), disciplinas (0.39), matricula (0.35), secretaria (0.28)\n", 531 | " Principais notícias relacionadas ao tópico:\n", 532 | "\t- Alunos de graduação: atenção ao cronograma do período de matrícula em disciplinas e de ajustes do 2º semestre de 2016 (0.55)\n", 533 | "\t- Atenção alunos de graduação: Retificação da relação de formandos para matrículas em disciplinas e ajuste de matrículas - 01/2017 (0.45)\n", 534 | "\t- Cronograma de matrículas em disciplinas e de ajustes de matrícula e relação de possíveis formandos (0.42)\n", 535 | "\t- ATENÇÃO ALUNOS DE GRADUAÇÃO DIVULGADO O NÚMERO DE VAGAS DISPONÍVEIS POR DISCIPLINA PARA O PERÍODO DE AJUSTE DE MATRÍCULAS (0.39)\n", 536 | "\t- Atenção Alunos de Graduação: Publicada a lista com os nomes dos possíveis formandos que terão prioridade no período de Matrículas em Disciplinas no 2º semestre de 2016 (0.37)\n", 537 | "\n", 538 | "Tópico 13\n", 539 | " Principais termos: ello (0.69), jr (0.58), consultoria (0.52), ellojr (0.22), empresa (0.18)\n", 540 | " Principais notícias relacionadas ao tópico:\n", 541 | "\t- Ello Consultoria Jr lança edital de seleção de novos trainees (0.52)\n", 542 | "\t- Ello Consultoria Jr lança edital de seleção de novos trainees (0.47)\n", 543 | "\t- Ello Consultoria Jr lança a primeira edição da Ello Revista de Negócios para Empresários Juniores (0.46)\n", 544 | "\t- Ello Consultoria Jr promove seleção de trainees e curso de Gerenciamento da Qualidade com ISO 9001 (0.43)\n", 545 | "\t- Ello Consultoria Jr convoca assembleia geral extraordinária para o dia 29 de abril (0.41)\n", 546 | "\n", 547 | "Tópico 14\n", 548 | " Principais termos: colegiados (0.65), compor (0.61), eleicao (0.55), tecnicos (0.5), integrados (0.49)\n", 549 | " Principais notícias relacionadas ao tópico:\n", 550 | "\t- Divulgada a homologação do resultado da eleição dos discentes para compor os colegiados dos cursos técnicos integrados ao ensino médio (0.46)\n", 551 | "\t- Divulgado o resultado da eleição dos discentes para compor os colegiados dos cursos técnicos integrados ao ensino médio (0.43)\n", 552 | "\t- Divulgada a homologação do resultado da eleição dos docentes para compor os colegiados dos cursos técnicos integrados ao ensino médio (0.42)\n", 553 | "\t- Campus Barbacena divulga impugnação e homologação dos inscritos para eleição de discentes para compor os colegiados dos cursos técnicos integrados ao ensino médio (0.42)\n", 554 | "\t- Divulgada a ordem dos discentes nas cédulas da eleição para compor os colegiados dos cursos técnicos integrados ao ensino médio (0.41)\n", 555 | "\n", 556 | "Tópico 15\n", 557 | " Principais termos: seminario (0.69), iii (0.58), trabalhos (0.31), mostra (0.28), extensao (0.19)\n", 558 | " Principais notícias relacionadas ao tópico:\n", 559 | "\t- Divulgada a programação da Semana Nacional de Ciência e Tecnologia 2016. Faça sua inscrição! (0.67)\n", 560 | "\t- Atenção: Modelos de apresentação para Mostra de Trabalho e III Seminário de Extensão (0.59)\n", 561 | "\t- Campus Barbacena divulga balanço da Semana Nacional de Ciência e Tecnologia 2016 (0.45)\n", 562 | "\t- Divulgado o Edital para o III Seminário de Ensino (0.42)\n", 563 | "\t- Divulgado o Edital do III Seminário de Extensão (0.34)\n", 564 | "\n", 565 | "Tópico 16\n", 566 | " Principais termos: rede (0.47), educacao (0.46), federal (0.41), tecnologica (0.36), profissional (0.36)\n", 567 | " Principais notícias relacionadas ao tópico:\n", 568 | "\t- Institutos Federais completam sete anos de educação pública, gratuita e de excelência (0.44)\n", 569 | "\t- Conif solicita inclusão da Rede Federal no resultado do Enem 2015 (0.4)\n", 570 | "\t- Institutos Federais completam oito anos (0.39)\n", 571 | "\t- Mestrado para servidores da Rede Federal abrirá primeira turma em 2017 (0.39)\n", 572 | "\t- Ministro da Educação participa da primeira reunião extraordinária do Conif em 2016 (0.38)\n", 573 | "\n", 574 | "Tópico 17\n", 575 | " Principais termos: edital (1.62), leia (0.67), 2016 (0.56), retificacao (0.4), inscricoes (0.3)\n", 576 | " Principais notícias relacionadas ao tópico:\n", 577 | "\t- Divulgado o Edital Retificado do Programa de Monitoria 2016-1 (0.27)\n", 578 | "\t- Estão abertas as inscrições para projetos de monitoria (2016 -2) (0.25)\n", 579 | "\t- Divulgado o Edital do Programa de Monitoria 2016-1 (0.23)\n", 580 | "\t- Estão abertas as inscrições para projetos de monitoria (2017 -2) (0.21)\n", 581 | "\t- Divulgado o Edital de chamada pública para seleção de extensionista colaborador externo (0.2)\n", 582 | "\n", 583 | "Tópico 18\n", 584 | " Principais termos: pibic (0.87), cnpq (0.73), pibicti (0.31), jr (0.2), af (0.19)\n", 585 | " Principais notícias relacionadas ao tópico:\n", 586 | "\t- Divulgado o Resultado final do Edital 04/2016 (0.68)\n", 587 | "\t- Divulgado o resultado final retificado do Edital 04/2016 - Edital Projetos de Iniciação Científica (0.67)\n", 588 | "\t- Campus divulga o Resultado Provisório dos projetos de iniciação científica encaminhados ao edital 04/2016 (2016/2017) (0.66)\n", 589 | "\t- Publicada Retificação para os editais 04 e 05/2016 - Programa Institucional de Iniciação Científica (0.47)\n", 590 | "\t- IF Sudeste MG publica editais de bolsas de iniciação científica (0.4)\n", 591 | "\n", 592 | "Tópico 19\n", 593 | " Principais termos: kb (1.28), anexotamanho (0.65), pdf107 (0.24), 78 (0.12), _resultado_definitivo (0.1)\n", 594 | " Principais notícias relacionadas ao tópico:\n", 595 | "\t- Edital de Convocação Eleitoral para escolha dos representantes dos servidores docentes, técnico-administrativos e discentes nas comissões eleitorais de Campus para escolha de Reitor do IF Sudeste MG e Diretores-gerais dos Campi (0.37)\n", 596 | "\t- Campus Barbacena divulga Edital de Extensão (0.35)\n", 597 | "\t- Divulgado resultado provisório do Programa de Assistência Estudantil 2017 (0.34)\n", 598 | "\t- Divulgado o resultado definitivo do Programa de Assistência Estudantil 2017 (0.34)\n", 599 | "\t- Divulgada a retificação do edital de eleições para Diretoria do CAAD (0.34)\n", 600 | "\n", 601 | "Tópico 20\n", 602 | " Principais termos: aviso (1.09), servico (0.33), setor (0.29), social (0.28), 8840 (0.27)\n", 603 | " Principais notícias relacionadas ao tópico:\n", 604 | "\t- Setor de Serviço Social divulga avisos (0.57)\n", 605 | "\t- Novos avisos do Setor de Serviço Social (0.56)\n", 606 | "\t- Atenção: Novo horário de funcionamento do Setor de Serviço Social (0.53)\n", 607 | "\t- Aviso do Setor de Serviço Social (0.47)\n", 608 | "\t- Divulgados o aviso e a relação de pendências do alunos candidatos ao Programa de Assistência Estudantil (0.4)\n", 609 | "\n", 610 | "Tópico 21\n", 611 | " Principais termos: protegidas (0.44), areas (0.36), pos (0.35), naturais (0.35), graduacao (0.29)\n", 612 | " Principais notícias relacionadas ao tópico:\n", 613 | "\t- Aula inaugural da pós-graduação discute “Sobrevivência humana e conservação no Parque Nacional de Virunga (0.61)\n", 614 | "\t- Professor do Campus Barbacena lança livro \"Áreas naturais protegidas e indicadores sócioeconômicos: o desafio da conservação da natureza\" (0.43)\n", 615 | "\t- Aula Magna do Curso de Pós-graduação em Planejamento e Gestão de Áreas Naturais Protegidas discute \"Ecologia e evolução\" (0.42)\n", 616 | "\t- Divulgado o Ciclo de Palestras sobre conservação da natureza (0.38)\n", 617 | "\t- Campus Barbacena divulga informações sobre o início das aulas do Curso de Pós-graduação lato sensu em \"Planejamento e Gestão de Áreas Naturais Protegidas\" (0.37)\n", 618 | "\n", 619 | "Tópico 22\n", 620 | " Principais termos: palestra (0.49), gefrut (0.46), auditorio (0.34), estudos (0.28), grupo (0.25)\n", 621 | " Principais notícias relacionadas ao tópico:\n", 622 | "\t- Grupo de Estudos - GEFRUT promove palestra sobre \"Pós-colheita de frutas\" (0.62)\n", 623 | "\t- Grupo de Estudos - GEFRUT promove palestra sobre \"Produção de Mudas de Pitaya\" (0.6)\n", 624 | "\t- Estudantes participam da palestra \"Pós-colheita de frutas\" (0.46)\n", 625 | "\t- O Grupo de Estudos - GEFRUT promove palestra sobre \"Segurança Alimentar na Fruticultura\" (0.45)\n", 626 | "\t- Gefrut debate Uso de telados em Fruticultura (0.36)\n", 627 | "\n", 628 | "Tópico 23\n", 629 | " Principais termos: documento (1.65), leia (1.24), divulgada (0.67), homologacao (0.39), dce (0.19)\n", 630 | " Principais notícias relacionadas ao tópico:\n", 631 | "\t- Atenção formandos dos Cursos de Nutrição e Licenciatura em Química (0.21)\n", 632 | "\t- Aviso Setor de Serviço Social (0.21)\n", 633 | "\t- Setor de Serviço Social divulga aviso (0.21)\n", 634 | "\t- Divulgada a homologação das chapas candidatas ao DCE 2017 (0.18)\n", 635 | "\t- Secretaria de Educação Superior divulga Cronograma de Matrícula em Disciplinas e a Relação de Possíveis Formandos para o 2º semestre de 2017 (0.16)\n", 636 | "\n", 637 | "Tópico 24\n", 638 | " Principais termos: fecib (0.55), trabalhos (0.5), vi (0.24), ou (0.22), categoria (0.2)\n", 639 | " Principais notícias relacionadas ao tópico:\n", 640 | "\t- Estão abertas as inscrições de trabalhos para a VI Feira Científica de Barbacena (VI FECIB) (0.76)\n", 641 | "\t- Estão abertas as inscrições de trabalhos para a V Feira Científica de Barbacena (V FECIB) (0.72)\n", 642 | "\t- IF Sudeste MG – Campus Barbacena realiza VI Feira Científica de Barbacena (FECIB) com 70 projetos de escolas de Barbacena (0.68)\n", 643 | "\t- IF Sudeste MG – Campus Barbacena realiza V Feira Científica de Barbacena com mais de 70 projetos de escolas de Barbacena (0.63)\n", 644 | "\t- Fecib movimenta Campus Barbacena com exposição de projetos (0.38)\n", 645 | "\n", 646 | "Tópico 25\n", 647 | " Principais termos: secao (0.33), alimentacao (0.32), nutricao (0.28), lanche (0.23), noturno (0.22)\n", 648 | " Principais notícias relacionadas ao tópico:\n", 649 | "\t- Seção de Alimentação e Nutrição publica comunicado sobre lanche noturno (0.81)\n", 650 | "\t- Seção de Alimentação e Nutrição começa a servir o lanche noturno (0.8)\n", 651 | "\t- Novo horário de funcionamento do almoço (0.48)\n", 652 | "\t- Comunicado: Alteração no horário do jantar (0.47)\n", 653 | "\t- Divulgado o horário de Funcionamento da SAN (SEÇÃO DE ALIMENTAÇÃO E NUTRIÇÃO) - CAMPUS BARBACENA no período de férias escolares (0.44)\n" 654 | ] 655 | } 656 | ], 657 | "source": [ 658 | "# Função para exibir os tópicos\n", 659 | "def exibe_topicos(H, W, feature_names, documents, num_top_words, num_top_documents):\n", 660 | " for topic_idx, topic in enumerate(H):\n", 661 | " print('\\nTópico %d' % (topic_idx + 1))\n", 662 | "\n", 663 | " print(' Principais termos: ' + ', '.join([feature_names[i] + ' (%s)' % round(H[topic_idx][i], 2) \n", 664 | " for i in topic.argsort()[:-num_top_words - 1:-1]])) \n", 665 | "\n", 666 | " # Top documentos relacionados\n", 667 | " print(' Principais notícias relacionadas ao tópico:')\n", 668 | "\n", 669 | " top_doc_indices = np.argsort( W[:,topic_idx] )[::-1][0:num_top_documents]\n", 670 | " for doc_index in top_doc_indices:\n", 671 | " # Id do documento\n", 672 | " id_doc = int(documents[doc_index].split('\\n')[0])\n", 673 | " \n", 674 | " # Texto\n", 675 | " texto = noticias[id_doc]['titulo']\n", 676 | " print('\\t-', texto, ' (%s)' % round(W[doc_index][topic_idx], 2))\n", 677 | "\n", 678 | "\n", 679 | "# Número de palavras mais relacionadas que serão exibidas para cada tópico\n", 680 | "num_top_words = 5\n", 681 | "\n", 682 | "# Número de documentos por tópico\n", 683 | "num_top_documents = 5\n", 684 | "\n", 685 | "exibe_topicos(nmf_H, nmf_W, tfidf_feature_names, documents, num_top_words, num_top_documents)" 686 | ] 687 | }, 688 | { 689 | "cell_type": "markdown", 690 | "metadata": {}, 691 | "source": [ 692 | "### Sistema de recomendação" 693 | ] 694 | }, 695 | { 696 | "cell_type": "code", 697 | "execution_count": 120, 698 | "metadata": {}, 699 | "outputs": [ 700 | { 701 | "name": "stdout", 702 | "output_type": "stream", 703 | "text": [ 704 | "- Jogos dos Institutos Federais movimentam comunidade acadêmica\n" 705 | ] 706 | }, 707 | { 708 | "data": { 709 | "text/plain": [ 710 | "array([ 2.22044605e-16, 5.52969170e-01, 7.07878718e-01,\n", 711 | " 7.09074804e-01, 7.31358349e-01])" 712 | ] 713 | }, 714 | "execution_count": 120, 715 | "metadata": {}, 716 | "output_type": "execute_result" 717 | } 718 | ], 719 | "source": [ 720 | "print('-', noticias[15]['titulo'])\n", 721 | "\n", 722 | "# Utiliza a matriz de distâncias precomputadas\n", 723 | "dist[15].sort()\n", 724 | "\n", 725 | "# 5 documentos mais \"próximos\" do documento 0\n", 726 | "sugestoes = dist[15][:5]\n", 727 | "\n", 728 | "for s in sugestoes\n", 729 | "\n" 730 | ] 731 | }, 732 | { 733 | "cell_type": "markdown", 734 | "metadata": {}, 735 | "source": [ 736 | "## Bônus" 737 | ] 738 | }, 739 | { 740 | "cell_type": "markdown", 741 | "metadata": {}, 742 | "source": [ 743 | "## Lemmatization\n", 744 | "\n", 745 | "Menos \"agressivo\" que o stemming" 746 | ] 747 | }, 748 | { 749 | "cell_type": "code", 750 | "execution_count": 122, 751 | "metadata": {}, 752 | "outputs": [ 753 | { 754 | "name": "stdout", 755 | "output_type": "stream", 756 | "text": [ 757 | "car\n", 758 | "box\n", 759 | "spy\n", 760 | "child\n" 761 | ] 762 | } 763 | ], 764 | "source": [ 765 | "from nltk.stem.wordnet import WordNetLemmatizer\n", 766 | "\n", 767 | "lmtzr = WordNetLemmatizer()\n", 768 | "\n", 769 | "print(lmtzr.lemmatize('cars'))\n", 770 | "print(lmtzr.lemmatize('boxes'))\n", 771 | "print(lmtzr.lemmatize('spies'))\n", 772 | "print(lmtzr.lemmatize('children'))" 773 | ] 774 | }, 775 | { 776 | "cell_type": "markdown", 777 | "metadata": {}, 778 | "source": [ 779 | "## Part-of-Speech Tagging (POS Tagging)" 780 | ] 781 | }, 782 | { 783 | "cell_type": "code", 784 | "execution_count": 123, 785 | "metadata": {}, 786 | "outputs": [ 787 | { 788 | "data": { 789 | "text/plain": [ 790 | "[('The', 'DT'),\n", 791 | " ('book', 'NN'),\n", 792 | " ('is', 'VBZ'),\n", 793 | " ('on', 'IN'),\n", 794 | " ('the', 'DT'),\n", 795 | " ('table', 'NN')]" 796 | ] 797 | }, 798 | "execution_count": 123, 799 | "metadata": {}, 800 | "output_type": "execute_result" 801 | } 802 | ], 803 | "source": [ 804 | "import nltk\n", 805 | "\n", 806 | "'''\n", 807 | " DT: Determiner\n", 808 | " NN: Noun, singular or mass \n", 809 | " VBZ: Verb, 3rd person singular present\n", 810 | " IN: Preposition or subordinating conjunction\n", 811 | "'''\n", 812 | "\n", 813 | "nltk.pos_tag(['The', 'book', 'is', 'on', 'the', 'table'])" 814 | ] 815 | }, 816 | { 817 | "cell_type": "markdown", 818 | "metadata": {}, 819 | "source": [ 820 | "## Análise de sentimentos\n", 821 | "\n", 822 | "VADER (Valence Aware Dictionary and sEntiment Reasoner)" 823 | ] 824 | }, 825 | { 826 | "cell_type": "code", 827 | "execution_count": 124, 828 | "metadata": {}, 829 | "outputs": [ 830 | { 831 | "name": "stdout", 832 | "output_type": "stream", 833 | "text": [ 834 | "{'compound': 0.743, 'neg': 0.0, 'pos': 0.677, 'neu': 0.323}\n" 835 | ] 836 | } 837 | ], 838 | "source": [ 839 | "from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer\n", 840 | "\n", 841 | "analyzer = SentimentIntensityAnalyzer()\n", 842 | "\n", 843 | "print(analyzer.polarity_scores('Machine learning is fun :)'))" 844 | ] 845 | }, 846 | { 847 | "cell_type": "code", 848 | "execution_count": null, 849 | "metadata": { 850 | "collapsed": true 851 | }, 852 | "outputs": [], 853 | "source": [] 854 | } 855 | ], 856 | "metadata": { 857 | "kernelspec": { 858 | "display_name": "Python 3", 859 | "language": "python", 860 | "name": "python3" 861 | }, 862 | "language_info": { 863 | "codemirror_mode": { 864 | "name": "ipython", 865 | "version": 3 866 | }, 867 | "file_extension": ".py", 868 | "mimetype": "text/x-python", 869 | "name": "python", 870 | "nbconvert_exporter": "python", 871 | "pygments_lexer": "ipython3", 872 | "version": "3.6.4" 873 | } 874 | }, 875 | "nbformat": 4, 876 | "nbformat_minor": 2 877 | } 878 | -------------------------------------------------------------------------------- /Aula 04.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Instituto Federal do Sudeste de Minas Gerais, Campus Barbacena\n", 8 | "### Projeto Laboratório de Redes de Conhecimento" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "## Curso de Mineração de Dados Aplicada\n", 16 | "\n", 17 | "Prof. Rafael José de Alencar Almeida\n", 18 | "\n", 19 | "\n", 20 | "
\n", 21 | "\n", 22 | "## Aula 4: Processamento de Linguagem Natural\n", 23 | "\n", 24 | "#### \"Estima-se que 80% de todo conteúdo mundial online são textos\"\n", 25 | "_Chen, H. Knowledge management systems: a text mining perspective. Arizona: Knowledge\n", 26 | "Computing Corporation. 2001._\n", 27 | "\n", 28 | "#### \"No geral, 80% das informações criadas e utilizadas por uma empresa são dados não estruturados, o que torna a manipulação e interpretação mais complexa\".\n", 29 | "_André Pannunzio, PricewaterhouseCoopers (PwC) Brasil._\n", 30 | "\n", 31 | "
\n", 32 | "\n", 33 | "\n", 34 | "\n", 35 | "Linguagem Natural: meio de comunicação utilizado pelos humanos para se comunicarem (idiomas e línguas de sinais).\n", 36 | "\n", 37 | "Processamento de linguagem natural (PLN): subárea da ciência da computação, inteligência artificial e da linguística que estuda os problemas da geração e compreensão automática de línguas humanas naturais." 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | " " 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "### Dataset: notícias IF\n", 52 | "\n" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": 15, 58 | "metadata": {}, 59 | "outputs": [ 60 | { 61 | "data": { 62 | "text/html": [ 63 | "
\n", 64 | "\n", 77 | "\n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | "
datatituloconteudo
014/09/2017Campus Barbacena divulga Resultado Provisório ...\\n\\n\\tO Campus Barbacena divulgou o Resultado ...
114/09/2017Divulgado o Edital de convocação de assembleia...\\n\\n\\tDivulgado o Edital de convocação de asse...
214/09/2017Pesquisador da Bélgica realiza palestra no Cam...\\n\\n\\tO pesquisador da Bélgica, Luc Vankrunkel...
314/09/2017Divulgada a homologação das inscrições à candi...\\n\\n\\tDivulgada a homologação das inscrições à...
414/09/2017Aprovado Regulamento de Eventos, Cerimonial e ...\\n\\n\\tO Regulamento, aprovado no dia 05 de set...
\n", 119 | "
" 120 | ], 121 | "text/plain": [ 122 | " data titulo \\\n", 123 | "0 14/09/2017 Campus Barbacena divulga Resultado Provisório ... \n", 124 | "1 14/09/2017 Divulgado o Edital de convocação de assembleia... \n", 125 | "2 14/09/2017 Pesquisador da Bélgica realiza palestra no Cam... \n", 126 | "3 14/09/2017 Divulgada a homologação das inscrições à candi... \n", 127 | "4 14/09/2017 Aprovado Regulamento de Eventos, Cerimonial e ... \n", 128 | "\n", 129 | " conteudo \n", 130 | "0 \\n\\n\\tO Campus Barbacena divulgou o Resultado ... \n", 131 | "1 \\n\\n\\tDivulgado o Edital de convocação de asse... \n", 132 | "2 \\n\\n\\tO pesquisador da Bélgica, Luc Vankrunkel... \n", 133 | "3 \\n\\n\\tDivulgada a homologação das inscrições à... \n", 134 | "4 \\n\\n\\tO Regulamento, aprovado no dia 05 de set... " 135 | ] 136 | }, 137 | "execution_count": 15, 138 | "metadata": {}, 139 | "output_type": "execute_result" 140 | } 141 | ], 142 | "source": [ 143 | "import pandas as pd\n", 144 | "\n", 145 | "df = pd.read_csv('df_noticias_if.csv')\n", 146 | "df.head()" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": 16, 152 | "metadata": {}, 153 | "outputs": [ 154 | { 155 | "data": { 156 | "text/plain": [ 157 | "data 14/09/2017\n", 158 | "titulo Campus Barbacena divulga Resultado Provisório ...\n", 159 | "conteudo \\n\\n\\tO Campus Barbacena divulgou o Resultado ...\n", 160 | "Name: 0, dtype: object" 161 | ] 162 | }, 163 | "execution_count": 16, 164 | "metadata": {}, 165 | "output_type": "execute_result" 166 | } 167 | ], 168 | "source": [ 169 | "df.iloc[0]" 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": 18, 175 | "metadata": {}, 176 | "outputs": [ 177 | { 178 | "name": "stdout", 179 | "output_type": "stream", 180 | "text": [ 181 | "\n", 182 | "\n", 183 | "\tO Campus Barbacena divulgou o Resultado Provisório do VIII Simpósio de Pesquisa e Inovação.\n", 184 | "\n", 185 | "\tOs estudantes devem ficar atentos as observações que constam no final do documento.\n", 186 | "\n", 187 | "Leia o documento\n", 188 | "\n" 189 | ] 190 | } 191 | ], 192 | "source": [ 193 | "print(df.iloc[0]['conteudo'])" 194 | ] 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "metadata": {}, 199 | "source": [ 200 | "### Pré-processamento\n", 201 | "\n", 202 | "Consiste em processar os textos antes de realizar sua conversão para um formato numérico." 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": 25, 208 | "metadata": {}, 209 | "outputs": [ 210 | { 211 | "data": { 212 | "text/plain": [ 213 | "'\\n\\n\\to campus barbacena divulgou o resultado provisório do viii simpósio de pesquisa e inovação.\\n\\n\\tos estudantes devem ficar atentos as observações que constam no final do documento.\\n\\nleia o documento\\n'" 214 | ] 215 | }, 216 | "execution_count": 25, 217 | "metadata": {}, 218 | "output_type": "execute_result" 219 | } 220 | ], 221 | "source": [ 222 | "# Conversão para minúsculas\n", 223 | "df.iloc[0]['conteudo'].lower()" 224 | ] 225 | }, 226 | { 227 | "cell_type": "markdown", 228 | "metadata": {}, 229 | "source": [ 230 | " " 231 | ] 232 | }, 233 | { 234 | "cell_type": "code", 235 | "execution_count": 26, 236 | "metadata": {}, 237 | "outputs": [ 238 | { 239 | "data": { 240 | "text/plain": [ 241 | "'!\"#$%&\\'()*+,-./:;<=>?@[\\\\]^_`{|}~'" 242 | ] 243 | }, 244 | "execution_count": 26, 245 | "metadata": {}, 246 | "output_type": "execute_result" 247 | } 248 | ], 249 | "source": [ 250 | "# Remoção de pontuação\n", 251 | "from string import punctuation\n", 252 | "\n", 253 | "punctuation" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": 29, 259 | "metadata": {}, 260 | "outputs": [ 261 | { 262 | "data": { 263 | "text/plain": [ 264 | "'\\n\\n\\tO Campus Barbacena divulgou o Resultado Provisório do VIII Simpósio de Pesquisa e Inovação\\n\\n\\tOs estudantes devem ficar atentos as observações que constam no final do documento\\n\\nLeia o documento\\n'" 265 | ] 266 | }, 267 | "execution_count": 29, 268 | "metadata": {}, 269 | "output_type": "execute_result" 270 | } 271 | ], 272 | "source": [ 273 | "''.join([l for l in df.iloc[0]['conteudo'] if l not in punctuation])" 274 | ] 275 | }, 276 | { 277 | "cell_type": "markdown", 278 | "metadata": {}, 279 | "source": [ 280 | " " 281 | ] 282 | }, 283 | { 284 | "cell_type": "code", 285 | "execution_count": 30, 286 | "metadata": {}, 287 | "outputs": [ 288 | { 289 | "data": { 290 | "text/plain": [ 291 | "'O Campus Barbacena divulgou o Resultado Provisório do VIII Simpósio de Pesquisa e Inovação.Os estudantes devem ficar atentos as observações que constam no final do documento.Leia o documento'" 292 | ] 293 | }, 294 | "execution_count": 30, 295 | "metadata": {}, 296 | "output_type": "execute_result" 297 | } 298 | ], 299 | "source": [ 300 | "# Substituição de caracteres\n", 301 | "df.iloc[0]['conteudo'].replace('\\n', '').replace('\\t', '')" 302 | ] 303 | }, 304 | { 305 | "cell_type": "code", 306 | "execution_count": 32, 307 | "metadata": {}, 308 | "outputs": [ 309 | { 310 | "data": { 311 | "text/plain": [ 312 | "'O Campus Barbacena divulgou o Resultado Provisório do VIII Simpósio de Pesquisa e Inovação.Os estudantes devem ficar atentos as observações que constam no final do documento.Leia o documento'" 313 | ] 314 | }, 315 | "execution_count": 32, 316 | "metadata": {}, 317 | "output_type": "execute_result" 318 | } 319 | ], 320 | "source": [ 321 | "# Substituição de caracteres com re\n", 322 | "import re\n", 323 | "\n", 324 | "re.sub(r'\\n|\\t', '', df.iloc[0]['conteudo'])" 325 | ] 326 | }, 327 | { 328 | "cell_type": "markdown", 329 | "metadata": {}, 330 | "source": [ 331 | " " 332 | ] 333 | }, 334 | { 335 | "cell_type": "code", 336 | "execution_count": 20, 337 | "metadata": {}, 338 | "outputs": [ 339 | { 340 | "name": "stdout", 341 | "output_type": "stream", 342 | "text": [ 343 | "['\\n\\n\\tO', 'Campus', 'Barbacena', 'divulgou', 'o', 'Resultado', 'Provisório', 'do', 'VIII', 'Simpósio', 'de', 'Pesquisa', 'e', 'Inovação.\\n\\n\\tOs', 'estudantes', 'devem', 'ficar', 'atentos', 'as', 'observações', 'que', 'constam', 'no', 'final', 'do', 'documento.\\n\\nLeia', 'o', 'documento\\n']\n" 344 | ] 345 | } 346 | ], 347 | "source": [ 348 | "# Tokenização com split\n", 349 | "print(df.iloc[0]['conteudo'].split(' '))" 350 | ] 351 | }, 352 | { 353 | "cell_type": "code", 354 | "execution_count": 24, 355 | "metadata": {}, 356 | "outputs": [ 357 | { 358 | "name": "stdout", 359 | "output_type": "stream", 360 | "text": [ 361 | "['O', 'Campus', 'Barbacena', 'divulgou', 'o', 'Resultado', 'Provisório', 'do', 'VIII', 'Simpósio', 'de', 'Pesquisa', 'e', 'Inovação', '.', 'Os', 'estudantes', 'devem', 'ficar', 'atentos', 'as', 'observações', 'que', 'constam', 'no', 'final', 'do', 'documento', '.', 'Leia', 'o', 'documento']\n" 362 | ] 363 | } 364 | ], 365 | "source": [ 366 | "# Tokenização com nltk\n", 367 | "from nltk import word_tokenize\n", 368 | "\n", 369 | "print(word_tokenize(df.iloc[0]['conteudo']))" 370 | ] 371 | }, 372 | { 373 | "cell_type": "markdown", 374 | "metadata": {}, 375 | "source": [ 376 | " " 377 | ] 378 | }, 379 | { 380 | "cell_type": "code", 381 | "execution_count": 33, 382 | "metadata": {}, 383 | "outputs": [ 384 | { 385 | "data": { 386 | "text/plain": [ 387 | "b'\\n\\n\\tO Campus Barbacena divulgou o Resultado Provisorio do VIII Simposio de Pesquisa e Inovacao.\\n\\n\\tOs estudantes devem ficar atentos as observacoes que constam no final do documento.\\n\\nLeia o documento\\n'" 388 | ] 389 | }, 390 | "execution_count": 33, 391 | "metadata": {}, 392 | "output_type": "execute_result" 393 | } 394 | ], 395 | "source": [ 396 | "# Remoção de acentos\n", 397 | "from unicodedata import normalize\n", 398 | "\n", 399 | "normalize('NFKD', df.iloc[0]['conteudo']).encode('ASCII', 'ignore')" 400 | ] 401 | }, 402 | { 403 | "cell_type": "markdown", 404 | "metadata": {}, 405 | "source": [ 406 | " " 407 | ] 408 | }, 409 | { 410 | "cell_type": "code", 411 | "execution_count": 37, 412 | "metadata": {}, 413 | "outputs": [ 414 | { 415 | "name": "stdout", 416 | "output_type": "stream", 417 | "text": [ 418 | "['de', 'a', 'o', 'que', 'e', 'do', 'da', 'em', 'um', 'para', 'com', 'não', 'uma', 'os', 'no', 'se', 'na', 'por', 'mais', 'as', 'dos', 'como', 'mas', 'ao', 'ele', 'das', 'à', 'seu', 'sua', 'ou', 'quando', 'muito', 'nos', 'já', 'eu', 'também', 'só', 'pelo', 'pela', 'até', 'isso', 'ela', 'entre', 'depois', 'sem', 'mesmo', 'aos', 'seus', 'quem', 'nas', 'me', 'esse', 'eles', 'você', 'essa', 'num', 'nem', 'suas', 'meu', 'às', 'minha', 'numa', 'pelos', 'elas', 'qual', 'nós', 'lhe', 'deles', 'essas', 'esses', 'pelas', 'este', 'dele', 'tu', 'te', 'vocês', 'vos', 'lhes', 'meus', 'minhas', 'teu', 'tua', 'teus', 'tuas', 'nosso', 'nossa', 'nossos', 'nossas', 'dela', 'delas', 'esta', 'estes', 'estas', 'aquele', 'aquela', 'aqueles', 'aquelas', 'isto', 'aquilo', 'estou', 'está', 'estamos', 'estão', 'estive', 'esteve', 'estivemos', 'estiveram', 'estava', 'estávamos', 'estavam', 'estivera', 'estivéramos', 'esteja', 'estejamos', 'estejam', 'estivesse', 'estivéssemos', 'estivessem', 'estiver', 'estivermos', 'estiverem', 'hei', 'há', 'havemos', 'hão', 'houve', 'houvemos', 'houveram', 'houvera', 'houvéramos', 'haja', 'hajamos', 'hajam', 'houvesse', 'houvéssemos', 'houvessem', 'houver', 'houvermos', 'houverem', 'houverei', 'houverá', 'houveremos', 'houverão', 'houveria', 'houveríamos', 'houveriam', 'sou', 'somos', 'são', 'era', 'éramos', 'eram', 'fui', 'foi', 'fomos', 'foram', 'fora', 'fôramos', 'seja', 'sejamos', 'sejam', 'fosse', 'fôssemos', 'fossem', 'for', 'formos', 'forem', 'serei', 'será', 'seremos', 'serão', 'seria', 'seríamos', 'seriam', 'tenho', 'tem', 'temos', 'tém', 'tinha', 'tínhamos', 'tinham', 'tive', 'teve', 'tivemos', 'tiveram', 'tivera', 'tivéramos', 'tenha', 'tenhamos', 'tenham', 'tivesse', 'tivéssemos', 'tivessem', 'tiver', 'tivermos', 'tiverem', 'terei', 'terá', 'teremos', 'terão', 'teria', 'teríamos', 'teriam']\n" 419 | ] 420 | } 421 | ], 422 | "source": [ 423 | "# Remoção de stopwords\n", 424 | "# Palavras frequentes mas com pouco significado semântico\n", 425 | "import nltk\n", 426 | "\n", 427 | "stopwords = nltk.corpus.stopwords.words('portuguese')\n", 428 | "print(stopwords)" 429 | ] 430 | }, 431 | { 432 | "cell_type": "code", 433 | "execution_count": 42, 434 | "metadata": {}, 435 | "outputs": [ 436 | { 437 | "name": "stdout", 438 | "output_type": "stream", 439 | "text": [ 440 | "['campus', 'barbacena', 'divulgou', 'resultado', 'provisório', 'viii', 'simpósio', 'pesquisa', 'inovação', 'estudantes', 'devem', 'ficar', 'atentos', 'observações', 'constam', 'final', 'documento', 'leia', 'documento']\n" 441 | ] 442 | } 443 | ], 444 | "source": [ 445 | "print([w for w in word_tokenize(df.iloc[0]['conteudo'].lower()) if (w not in stopwords) and (w not in punctuation)])" 446 | ] 447 | }, 448 | { 449 | "cell_type": "markdown", 450 | "metadata": {}, 451 | "source": [ 452 | " " 453 | ] 454 | }, 455 | { 456 | "cell_type": "code", 457 | "execution_count": 45, 458 | "metadata": {}, 459 | "outputs": [ 460 | { 461 | "data": { 462 | "text/plain": [ 463 | "('program', 'program', 'program')" 464 | ] 465 | }, 466 | "execution_count": 45, 467 | "metadata": {}, 468 | "output_type": "execute_result" 469 | } 470 | ], 471 | "source": [ 472 | "# Stemming\n", 473 | "# Redução do termo a seu radical\n", 474 | "\n", 475 | "stemmer = nltk.stem.RSLPStemmer()\n", 476 | "\n", 477 | "stemmer.stem('programar'), stemmer.stem('programava'), stemmer.stem('programaremos')" 478 | ] 479 | }, 480 | { 481 | "cell_type": "markdown", 482 | "metadata": {}, 483 | "source": [ 484 | " " 485 | ] 486 | }, 487 | { 488 | "cell_type": "code", 489 | "execution_count": 51, 490 | "metadata": {}, 491 | "outputs": [ 492 | { 493 | "data": { 494 | "text/plain": [ 495 | "('car', 'box', 'spy', 'child')" 496 | ] 497 | }, 498 | "execution_count": 51, 499 | "metadata": {}, 500 | "output_type": "execute_result" 501 | } 502 | ], 503 | "source": [ 504 | "# Lemmatization (EN)\n", 505 | "# Menos \"agressivo\" que o stemming\n", 506 | "from nltk.stem.wordnet import WordNetLemmatizer\n", 507 | "\n", 508 | "lmtzr = WordNetLemmatizer()\n", 509 | "\n", 510 | "lmtzr.lemmatize('cars'), lmtzr.lemmatize('boxes'), lmtzr.lemmatize('spies'), lmtzr.lemmatize('children')" 511 | ] 512 | }, 513 | { 514 | "cell_type": "markdown", 515 | "metadata": {}, 516 | "source": [ 517 | " " 518 | ] 519 | }, 520 | { 521 | "cell_type": "code", 522 | "execution_count": 52, 523 | "metadata": {}, 524 | "outputs": [ 525 | { 526 | "data": { 527 | "text/plain": [ 528 | "[('the', 'DT'),\n", 529 | " ('book', 'NN'),\n", 530 | " ('is', 'VBZ'),\n", 531 | " ('on', 'IN'),\n", 532 | " ('the', 'DT'),\n", 533 | " ('table', 'NN')]" 534 | ] 535 | }, 536 | "execution_count": 52, 537 | "metadata": {}, 538 | "output_type": "execute_result" 539 | } 540 | ], 541 | "source": [ 542 | "# Parts of Speech Tagging (EN)\n", 543 | "nltk.pos_tag('the book is on the table'.split())" 544 | ] 545 | }, 546 | { 547 | "cell_type": "markdown", 548 | "metadata": {}, 549 | "source": [ 550 | " " 551 | ] 552 | }, 553 | { 554 | "cell_type": "code", 555 | "execution_count": 89, 556 | "metadata": {}, 557 | "outputs": [ 558 | { 559 | "data": { 560 | "text/plain": [ 561 | "0 campus barbacena divulga resultado provisório ...\n", 562 | "1 divulgado edital convocação assembleia centro ...\n", 563 | "2 pesquisador bélgica realiza palestra campus ba...\n", 564 | "3 divulgada homologação inscrições candidatura c...\n", 565 | "4 aprovado regulamento eventos cerimonial protoc...\n", 566 | "Name: doc, dtype: object" 567 | ] 568 | }, 569 | "execution_count": 89, 570 | "metadata": {}, 571 | "output_type": "execute_result" 572 | } 573 | ], 574 | "source": [ 575 | "# Gerando uma coluna de texto pré-processado (título + conteúdo)\n", 576 | "def processa(row):\n", 577 | " txt = row['titulo'] + ' ' + row['conteudo']\n", 578 | " \n", 579 | " return ' '.join([t for t in word_tokenize(txt.lower()) if (t not in stopwords) and (t not in punctuation)])\n", 580 | "\n", 581 | "df['doc'] = df.apply(processa, axis=1)\n", 582 | "\n", 583 | "df['doc'].head()" 584 | ] 585 | }, 586 | { 587 | "cell_type": "markdown", 588 | "metadata": {}, 589 | "source": [ 590 | " " 591 | ] 592 | }, 593 | { 594 | "cell_type": "markdown", 595 | "metadata": {}, 596 | "source": [ 597 | "### Vetorização\n", 598 | "\n", 599 | "Conversão dos textos para uma representação numérica. \n", 600 | "\n", 601 | "Forma básica: TF (Term Frequency)\n", 602 | "\n", 603 | "" 604 | ] 605 | }, 606 | { 607 | "cell_type": "code", 608 | "execution_count": 68, 609 | "metadata": {}, 610 | "outputs": [ 611 | { 612 | "data": { 613 | "text/plain": [ 614 | "<1000x10987 sparse matrix of type ''\n", 615 | "\twith 67457 stored elements in Compressed Sparse Row format>" 616 | ] 617 | }, 618 | "execution_count": 68, 619 | "metadata": {}, 620 | "output_type": "execute_result" 621 | } 622 | ], 623 | "source": [ 624 | "from sklearn.feature_extraction.text import TfidfVectorizer\n", 625 | "\n", 626 | "vectorizer = TfidfVectorizer(\n", 627 | " analyzer='word',\n", 628 | " ngram_range=(1, 1),\n", 629 | " max_features=None,\n", 630 | " binary=False,\n", 631 | " use_idf=True\n", 632 | ")\n", 633 | "tfidf_matrix = vectorizer.fit_transform(df['doc'])\n", 634 | "\n", 635 | "tfidf_matrix" 636 | ] 637 | }, 638 | { 639 | "cell_type": "markdown", 640 | "metadata": {}, 641 | "source": [ 642 | " " 643 | ] 644 | }, 645 | { 646 | "cell_type": "code", 647 | "execution_count": 91, 648 | "metadata": {}, 649 | "outputs": [ 650 | { 651 | "name": "stdout", 652 | "output_type": "stream", 653 | "text": [ 654 | "['00', '000', '000957', '001', '002', '002084', '002086', '003', '003360', '008', '009', '01', '012', '018', '02', '020', '021', '022', '03', '031', '032', '036', '039', '03dez2015', '04', '05', '050617', '052', '056', '05_final', '06', '06h30', '07', '072016', '07h', '07h00', '07h30', '08', '08h', '08h00min', '08h30', '08h30min', '09', '09h', '09h00min', '09h30', '09h30min', '10', '100', '1000', '10024', '106', '107', '109', '10h', '10h00min', '10h30', '10h30m', '10h30min', '10h45mim', '10h45min', '10ª', '10º', '11', '110', '115', '116257', '11h', '11h00', '11h00min', '11h10min', '11h30', '11h30min', '11h40', '11ª', '11º', '12', '120', '121', '125', '1256', '128', '1283', '129', '12h', '12h00min', '12h30', '13', '136', '13h', '13h00', '13h00min', '13h10min', '13h30', '13h30min', '13ª', '14', '140', '141', '143', '145', '146', '149', '14h', '14h00min', '14h30', '14hlocal', '14qualidadedevidaedoambiente', '15', '150', '15h', '15h30', '15h30min', '16', '160', '164', '166', '16h', '16h00min', '16h30', '16h50', '17', '170', '172', '175', '179', '17h', '17h00min', '17h30', '17h30min', '17h45', '17ª', '18', '180', '1827', '185', '189', '18h', '18h00min', '18h15min', '18h30', '18h30min', '18ª', '19', '1909', '191', '1910', '192', '1927', '1927an4vppuglifzxylp9u4ogs', '1932', '1945', '1947', '1972', '1979', '1983', '1984', '1986', '1987', '1992', '1993', '1994', '1995', '1999', '19h', '19h00', '19h00min', '19h15', '19h15min', '19h30', '19h45', '19jifsghun', '19ª', '1_2lgnzzc9ekuu4g5xtn66opwkev5txvea4ivqmh6ycy', '1_uvu7iyigo5d6qfhehvmvop3wxgapk1pdeyr1uvvkqc', '1a', '1aalfne7h4grxa0mkurk7gg4pei5efmmsby54gluw4o4', '1ahcf2vzkiuk9ftljgn_f62esex2wjgww7ivaidltriu', '1asd8wjjwq0ini_tt_jgkzkhepxzdnpagumav8gus5_8', '1azedtlmijk2u', '1bahgg', '1csgcyirajzo4m9hjt2tt_kun6qexqgaybamatk0kky0', '1d4', '1di0b8l8hhcmuicpls6p9vs5ub1xkneyujupfspjia_i', '1dwra7owoaosxovdphuwwhcijahahtqwd88bsiudoyru', '1e09fsvlgbghxb_4d6s9hzqrgt6cur2jbzqingdagxse', '1ed', '1erhcwwkmynbmj0yqejhidawaso2u4u', '1ezktrujmohi', '1faipqlscdlziuyyujafh', '1faipqlscemesh6sdpexovfoqhkvcuckvqnvmnwlchtjgheebxodxohw', '1faipqlscsciawacjjishc53hd', '1faipqlscsve_rzttqs9cnvefg', '1faipqlse5t97v1xbrt2q9xqprrf9gqux7hlo79v6kqkyrlksbryzqtg', '1faipqlsercvcmvhzzn_v0w_8umgdkfjr_qswcmoxydghams29b6ihgq', '1fhbbwdgb1_7jciglamojrwro5uiunebmgadhethfsk0', '1fn8_ymysoveepdturcpigwh8kyuotqi2rqorfs6nhsa', '1fxznjaceqieo_r', '1g5rbhfyjxh6wy3yfqv77_yvng6swnsxoxw3dvezl5c0', '1g9lbd7xhlt9hotp2']\n" 655 | ] 656 | } 657 | ], 658 | "source": [ 659 | "# Labels das colunas\n", 660 | "print(vectorizer.get_feature_names()[:200])\n", 661 | "\n", 662 | "# Precisamos melhorar o pré-processamento, vieram números e partes de links!" 663 | ] 664 | }, 665 | { 666 | "cell_type": "markdown", 667 | "metadata": {}, 668 | "source": [ 669 | " " 670 | ] 671 | }, 672 | { 673 | "cell_type": "code", 674 | "execution_count": 86, 675 | "metadata": {}, 676 | "outputs": [ 677 | { 678 | "data": { 679 | "text/html": [ 680 | "
\n", 681 | "\n", 694 | "\n", 695 | " \n", 696 | " \n", 697 | " \n", 698 | " \n", 699 | " \n", 700 | " \n", 701 | " \n", 702 | " \n", 703 | " \n", 704 | " \n", 705 | " \n", 706 | " \n", 707 | " \n", 708 | " \n", 709 | " \n", 710 | " \n", 711 | " \n", 712 | " \n", 713 | " \n", 714 | " \n", 715 | " \n", 716 | " \n", 717 | " \n", 718 | " \n", 719 | " \n", 720 | " \n", 721 | " \n", 722 | " \n", 723 | " \n", 724 | " \n", 725 | " \n", 726 | " \n", 727 | " \n", 728 | " \n", 729 | " \n", 730 | " \n", 731 | " \n", 732 | " \n", 733 | " \n", 734 | " \n", 735 | " \n", 736 | " \n", 737 | " \n", 738 | " \n", 739 | " \n", 740 | " \n", 741 | " \n", 742 | " \n", 743 | " \n", 744 | " \n", 745 | " \n", 746 | " \n", 747 | " \n", 748 | " \n", 749 | " \n", 750 | " \n", 751 | " \n", 752 | " \n", 753 | " \n", 754 | " \n", 755 | " \n", 756 | " \n", 757 | " \n", 758 | " \n", 759 | " \n", 760 | " \n", 761 | " \n", 762 | " \n", 763 | " \n", 764 | " \n", 765 | " \n", 766 | " \n", 767 | " \n", 768 | " \n", 769 | " \n", 770 | " \n", 771 | " \n", 772 | " \n", 773 | " \n", 774 | " \n", 775 | " \n", 776 | " \n", 777 | " \n", 778 | " \n", 779 | " \n", 780 | " \n", 781 | " \n", 782 | " \n", 783 | " \n", 784 | " \n", 785 | " \n", 786 | " \n", 787 | " \n", 788 | " \n", 789 | " \n", 790 | " \n", 791 | " \n", 792 | " \n", 793 | " \n", 794 | " \n", 795 | " \n", 796 | " \n", 797 | " \n", 798 | " \n", 799 | " \n", 800 | " \n", 801 | " \n", 802 | " \n", 803 | " \n", 804 | " \n", 805 | " \n", 806 | " \n", 807 | " \n", 808 | " \n", 809 | " \n", 810 | " \n", 811 | " \n", 812 | " \n", 813 | " \n", 814 | " \n", 815 | " \n", 816 | " \n", 817 | " \n", 818 | " \n", 819 | " \n", 820 | " \n", 821 | " \n", 822 | " \n", 823 | " \n", 824 | " \n", 825 | " \n", 826 | " \n", 827 | " \n", 828 | " \n", 829 | " \n", 830 | " \n", 831 | " \n", 832 | " \n", 833 | " \n", 834 | " \n", 835 | " \n", 836 | " \n", 837 | " \n", 838 | " \n", 839 | " \n", 840 | " \n", 841 | " \n", 842 | " \n", 843 | "
00000000957001002002084002086003003360008...últimoúltimosúnicaúnicasúnicoúnicosúteisúteroútilútimo
00.00.00.00.00.00.00.00.00.00.0...0.00.00.0000000.00.00.00.00.00.00.0
10.00.00.00.00.00.00.00.00.00.0...0.00.00.0000000.00.00.00.00.00.00.0
20.00.00.00.00.00.00.00.00.00.0...0.00.00.0000000.00.00.00.00.00.00.0
30.00.00.00.00.00.00.00.00.00.0...0.00.00.2010940.00.00.00.00.00.00.0
40.00.00.00.00.00.00.00.00.00.0...0.00.00.0000000.00.00.00.00.00.00.0
\n", 844 | "

5 rows × 10987 columns

\n", 845 | "
" 846 | ], 847 | "text/plain": [ 848 | " 00 000 000957 001 002 002084 002086 003 003360 008 ... \\\n", 849 | "0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... \n", 850 | "1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... \n", 851 | "2 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... \n", 852 | "3 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... \n", 853 | "4 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... \n", 854 | "\n", 855 | " último últimos única únicas único únicos úteis útero útil útimo \n", 856 | "0 0.0 0.0 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", 857 | "1 0.0 0.0 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", 858 | "2 0.0 0.0 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", 859 | "3 0.0 0.0 0.201094 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", 860 | "4 0.0 0.0 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", 861 | "\n", 862 | "[5 rows x 10987 columns]" 863 | ] 864 | }, 865 | "execution_count": 86, 866 | "metadata": {}, 867 | "output_type": "execute_result" 868 | } 869 | ], 870 | "source": [ 871 | "# Visualização da matriz na forma densa (DataFrame)\n", 872 | "pd.DataFrame(tfidf_matrix.todense(), columns=vectorizer.get_feature_names()).head()" 873 | ] 874 | }, 875 | { 876 | "cell_type": "markdown", 877 | "metadata": {}, 878 | "source": [ 879 | "### Similaridade textual\n", 880 | "\n", 881 | "Utiliza o espaço vetorial para calcular a distância entre cada texto.\n", 882 | "\n", 883 | "\n", 884 | "Fonte: http://bitsearch.blogspot.com/2011/01/vector-space-model-for-scoring.html" 885 | ] 886 | }, 887 | { 888 | "cell_type": "code", 889 | "execution_count": 121, 890 | "metadata": {}, 891 | "outputs": [ 892 | { 893 | "data": { 894 | "text/plain": [ 895 | "(1000, 1000)" 896 | ] 897 | }, 898 | "execution_count": 121, 899 | "metadata": {}, 900 | "output_type": "execute_result" 901 | } 902 | ], 903 | "source": [ 904 | "from sklearn.metrics.pairwise import cosine_similarity\n", 905 | "\n", 906 | "# Calcula todas as similaridades de cada linha\n", 907 | "sim = cosine_similarity(tfidf_matrix)\n", 908 | "\n", 909 | "sim.shape" 910 | ] 911 | }, 912 | { 913 | "cell_type": "code", 914 | "execution_count": 127, 915 | "metadata": {}, 916 | "outputs": [ 917 | { 918 | "data": { 919 | "text/plain": [ 920 | "0.04840608582716853" 921 | ] 922 | }, 923 | "execution_count": 127, 924 | "metadata": {}, 925 | "output_type": "execute_result" 926 | } 927 | ], 928 | "source": [ 929 | "# Similaridade entre o primeiro e o segundo texto\n", 930 | "sim[0][1]" 931 | ] 932 | }, 933 | { 934 | "cell_type": "code", 935 | "execution_count": 128, 936 | "metadata": {}, 937 | "outputs": [ 938 | { 939 | "data": { 940 | "text/plain": [ 941 | "0.0" 942 | ] 943 | }, 944 | "execution_count": 128, 945 | "metadata": {}, 946 | "output_type": "execute_result" 947 | } 948 | ], 949 | "source": [ 950 | "# Similaridade entre o primeiro e o centésimo texto\n", 951 | "sim[0][100]" 952 | ] 953 | }, 954 | { 955 | "cell_type": "code", 956 | "execution_count": 99, 957 | "metadata": {}, 958 | "outputs": [ 959 | { 960 | "data": { 961 | "text/plain": [ 962 | "'campus barbacena divulga resultado provisório viii simpósio pesquisa inovação campus barbacena divulgou resultado provisório viii simpósio pesquisa inovação estudantes devem ficar atentos observações constam final documento leia documento'" 963 | ] 964 | }, 965 | "execution_count": 99, 966 | "metadata": {}, 967 | "output_type": "execute_result" 968 | } 969 | ], 970 | "source": [ 971 | "df.iloc[0].doc" 972 | ] 973 | }, 974 | { 975 | "cell_type": "code", 976 | "execution_count": 100, 977 | "metadata": {}, 978 | "outputs": [ 979 | { 980 | "data": { 981 | "text/plain": [ 982 | "'divulgado edital convocação assembleia centro acadêmico nutrição divulgado edital convocação assembleia centro acadêmico nutrição leia documento'" 983 | ] 984 | }, 985 | "execution_count": 100, 986 | "metadata": {}, 987 | "output_type": "execute_result" 988 | } 989 | ], 990 | "source": [ 991 | "df.iloc[1].doc" 992 | ] 993 | }, 994 | { 995 | "cell_type": "code", 996 | "execution_count": 112, 997 | "metadata": {}, 998 | "outputs": [ 999 | { 1000 | "data": { 1001 | "text/plain": [ 1002 | "'centro memória diaulas abreu reaberto dia 07 agosto centro memória diaulas abreu reaberto visitação novo horário funcionamento 08h 12h 13h 17h agendamentos visitas podem ser realizados contato 32 9 84868411 32 9 82247002 foto rachel santos'" 1003 | ] 1004 | }, 1005 | "execution_count": 112, 1006 | "metadata": {}, 1007 | "output_type": "execute_result" 1008 | } 1009 | ], 1010 | "source": [ 1011 | "df.iloc[100].doc" 1012 | ] 1013 | }, 1014 | { 1015 | "cell_type": "code", 1016 | "execution_count": 150, 1017 | "metadata": {}, 1018 | "outputs": [ 1019 | { 1020 | "data": { 1021 | "text/plain": [ 1022 | "163" 1023 | ] 1024 | }, 1025 | "execution_count": 150, 1026 | "metadata": {}, 1027 | "output_type": "execute_result" 1028 | } 1029 | ], 1030 | "source": [ 1031 | "# Similaridade via distância de Levenshtein\n", 1032 | "from Levenshtein import distance\n", 1033 | "\n", 1034 | "distance(\n", 1035 | " df.iloc[0].doc,\n", 1036 | " df.iloc[1].doc\n", 1037 | ")" 1038 | ] 1039 | }, 1040 | { 1041 | "cell_type": "code", 1042 | "execution_count": 151, 1043 | "metadata": {}, 1044 | "outputs": [ 1045 | { 1046 | "data": { 1047 | "text/plain": [ 1048 | "189" 1049 | ] 1050 | }, 1051 | "execution_count": 151, 1052 | "metadata": {}, 1053 | "output_type": "execute_result" 1054 | } 1055 | ], 1056 | "source": [ 1057 | "distance(\n", 1058 | " df.iloc[0].doc,\n", 1059 | " df.iloc[100].doc\n", 1060 | ")" 1061 | ] 1062 | }, 1063 | { 1064 | "cell_type": "markdown", 1065 | "metadata": {}, 1066 | "source": [ 1067 | " " 1068 | ] 1069 | }, 1070 | { 1071 | "cell_type": "markdown", 1072 | "metadata": {}, 1073 | "source": [ 1074 | "## Análise de sentimentos\n", 1075 | "\n", 1076 | "Detectar automaticamente a polaridade e intensidade do sentimento expresso em um texto." 1077 | ] 1078 | }, 1079 | { 1080 | "cell_type": "markdown", 1081 | "metadata": {}, 1082 | "source": [ 1083 | "### LeIA (Léxico para Inferência Adaptada)\n", 1084 | "\n", 1085 | "LeIA (Léxico para Inferência Adaptada) é um fork do léxico e ferramenta para análise de sentimentos VADER (Valence Aware Dictionary and sEntiment Reasoner) adaptado para textos em português, com suporte para emojis e foco na análise de sentimentos de textos expressos em mídias sociais - mas funcional para textos de outros domínios.\n", 1086 | "\n", 1087 | "https://github.com/rafjaa/LeIA" 1088 | ] 1089 | }, 1090 | { 1091 | "cell_type": "markdown", 1092 | "metadata": {}, 1093 | "source": [ 1094 | "A biblioteca preserva a API do VADER, e o texto de entrada não precisa ser pré-processado:" 1095 | ] 1096 | }, 1097 | { 1098 | "cell_type": "code", 1099 | "execution_count": 138, 1100 | "metadata": {}, 1101 | "outputs": [], 1102 | "source": [ 1103 | "from leia import SentimentIntensityAnalyzer \n", 1104 | "\n", 1105 | "s = SentimentIntensityAnalyzer()" 1106 | ] 1107 | }, 1108 | { 1109 | "cell_type": "code", 1110 | "execution_count": 135, 1111 | "metadata": {}, 1112 | "outputs": [ 1113 | { 1114 | "data": { 1115 | "text/plain": [ 1116 | "{'compound': 0.6249, 'neg': 0.0, 'neu': 0.328, 'pos': 0.672}" 1117 | ] 1118 | }, 1119 | "execution_count": 135, 1120 | "metadata": {}, 1121 | "output_type": "execute_result" 1122 | } 1123 | ], 1124 | "source": [ 1125 | "# Análise de texto simples\n", 1126 | "s.polarity_scores('Eu estou feliz')" 1127 | ] 1128 | }, 1129 | { 1130 | "cell_type": "code", 1131 | "execution_count": 136, 1132 | "metadata": {}, 1133 | "outputs": [ 1134 | { 1135 | "data": { 1136 | "text/plain": [ 1137 | "{'compound': 0.7964, 'neg': 0.0, 'neu': 0.22, 'pos': 0.78}" 1138 | ] 1139 | }, 1140 | "execution_count": 136, 1141 | "metadata": {}, 1142 | "output_type": "execute_result" 1143 | } 1144 | ], 1145 | "source": [ 1146 | "# Análise de texto com emoji :)\n", 1147 | "s.polarity_scores('Eu estou feliz :)')" 1148 | ] 1149 | }, 1150 | { 1151 | "cell_type": "code", 1152 | "execution_count": 137, 1153 | "metadata": {}, 1154 | "outputs": [ 1155 | { 1156 | "data": { 1157 | "text/plain": [ 1158 | "{'compound': 0.4404, 'neg': 0.265, 'neu': 0.241, 'pos': 0.494}" 1159 | ] 1160 | }, 1161 | "execution_count": 137, 1162 | "metadata": {}, 1163 | "output_type": "execute_result" 1164 | } 1165 | ], 1166 | "source": [ 1167 | "# Análise de texto com negação\n", 1168 | "s.polarity_scores('Eu não estou feliz')" 1169 | ] 1170 | }, 1171 | { 1172 | "cell_type": "markdown", 1173 | "metadata": {}, 1174 | "source": [ 1175 | " " 1176 | ] 1177 | }, 1178 | { 1179 | "cell_type": "markdown", 1180 | "metadata": {}, 1181 | "source": [ 1182 | "A saída da análise de sentimentos é um dicionário com os seguintes campos:\n", 1183 | "\n", 1184 | "- pos: porcentagem positiva do texto\n", 1185 | "- neg: porcentagem negativa do texto\n", 1186 | "- neu: porcentagem neutra do texto\n", 1187 | "- compound: valor de sentimento geral normalizado, variando de -1 (extremamente negativo) a +1 (extremamente positivo)\n", 1188 | "\n", 1189 | "O valor compound pode ser utilizado para descrever o sentimento predominante no texto, por meio dos limites de valores:\n", 1190 | "\n", 1191 | "- Sentimento positivo: compound >= 0.05\n", 1192 | "- Sentimento negativo: compound <= -0.05\n", 1193 | "- Sentimento neutro: (compound > -0.05) and (compound < 0.05)" 1194 | ] 1195 | }, 1196 | { 1197 | "cell_type": "markdown", 1198 | "metadata": {}, 1199 | "source": [ 1200 | " " 1201 | ] 1202 | }, 1203 | { 1204 | "cell_type": "markdown", 1205 | "metadata": {}, 1206 | "source": [ 1207 | "## Atividade para sala\n", 1208 | "\n", 1209 | "Realizar análise de sentimentos dos dados de um site ou API.\n", 1210 | "\n", 1211 | "Exemplo: programa que coleta as notícias do Barbacena Online, analisa seus sentimentos, e exibe o título das notícias, da mais positiva para a mais negativa." 1212 | ] 1213 | }, 1214 | { 1215 | "cell_type": "markdown", 1216 | "metadata": {}, 1217 | "source": [ 1218 | "## Atividade para casa\n", 1219 | "\n", 1220 | "\n", 1221 | "Implementar um sistema de recomendação de notícias para o site do campus: dado o título e o conteúdo de uma nova notícia, indicar as 5 mais semelhantes." 1222 | ] 1223 | } 1224 | ], 1225 | "metadata": { 1226 | "kernelspec": { 1227 | "display_name": "Python 3", 1228 | "language": "python", 1229 | "name": "python3" 1230 | }, 1231 | "language_info": { 1232 | "codemirror_mode": { 1233 | "name": "ipython", 1234 | "version": 3 1235 | }, 1236 | "file_extension": ".py", 1237 | "mimetype": "text/x-python", 1238 | "name": "python", 1239 | "nbconvert_exporter": "python", 1240 | "pygments_lexer": "ipython3", 1241 | "version": "3.6.4" 1242 | } 1243 | }, 1244 | "nbformat": 4, 1245 | "nbformat_minor": 2 1246 | } 1247 | -------------------------------------------------------------------------------- /Aula08/static/jquery.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */ 2 | !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function e(t){return"function"==typeof t&&"number"!=typeof t.nodeType},y=function e(t){return null!=t&&t===t.window},v={type:!0,src:!0,noModule:!0};function m(e,t,n){var i,o=(t=t||r).createElement("script");if(o.text=e,n)for(i in v)n[i]&&(o[i]=n[i]);t.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[c.call(e)]||"object":typeof e}var b="3.3.1",w=function(e,t){return new w.fn.init(e,t)},T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;w.fn=w.prototype={jquery:"3.3.1",constructor:w,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return w.each(this,e)},map:function(e){return this.pushStack(w.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b="sizzle"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n+~]|"+M+")"+M+"*"),z=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),X=new RegExp(W),U=new RegExp("^"+R+"$"),V={ID:new RegExp("^#("+R+")"),CLASS:new RegExp("^\\.("+R+")"),TAG:new RegExp("^("+R+"|[*])"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ee=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},te=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ne=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},re=function(){p()},ie=me(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{L.apply(A=H.call(w.childNodes),w.childNodes),A[w.childNodes.length].nodeType}catch(e){L={apply:A.length?function(e,t){q.apply(e,H.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function oe(e,t,r,i){var o,s,l,c,f,h,v,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=J.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return L.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return L.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!S[e+" "]&&(!y||!y.test(e))){if(1!==T)m=t,v=e;else if("object"!==t.nodeName.toLowerCase()){(c=t.getAttribute("id"))?c=c.replace(te,ne):t.setAttribute("id",c=b),s=(h=a(e)).length;while(s--)h[s]="#"+c+" "+ve(h[s]);v=h.join(","),m=K.test(e)&&ge(t.parentNode)||t}if(v)try{return L.apply(r,m.querySelectorAll(v)),r}catch(e){}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ue(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function ce(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function pe(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ie(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function he(e){return se(function(t){return t=+t,se(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ge(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}n=oe.support={},o=oe.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},p=oe.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(d=a,h=d.documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",re,!1):i.attachEvent&&i.attachEvent("onunload",re)),n.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ue(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Q.test(d.getElementsByClassName),n.getById=ue(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&g)return t.getElementsByClassName(e)},v=[],y=[],(n.qsa=Q.test(d.querySelectorAll))&&(ue(function(e){h.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||y.push("~="),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||y.push(".#.+[+~]")}),ue(function(e){e.innerHTML="";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(n.matchesSelector=Q.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ue(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),v.push("!=",W)}),y=y.length&&new RegExp(y.join("|")),v=v.length&&new RegExp(v.join("|")),t=Q.test(h.compareDocumentPosition),x=t||Q.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?O(c,e)-O(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?O(c,e)-O(c,t):0;if(i===o)return ce(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?ce(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},oe.matches=function(e,t){return oe(e,null,null,t)},oe.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),t=t.replace(z,"='$1']"),n.matchesSelector&&g&&!S[t+" "]&&(!v||!v.test(t))&&(!y||!y.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return oe(t,d,null,[e]).length>0},oe.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},oe.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&N.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},oe.escape=function(e){return(e+"").replace(te,ne)},oe.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},oe.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(D),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return c=null,e},i=oe.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=oe.selectors={cacheLength:50,createPseudo:se,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Z,ee),e[3]=(e[3]||e[4]||e[5]||"").replace(Z,ee),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||oe.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&oe.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Z,ee).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=oe.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace($," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",y=t.parentNode,v=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(y){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?y.firstChild:y.lastChild],a&&m){x=(d=(l=(c=(f=(p=y)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&y.childNodes[d];while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===v:1===p.nodeType)&&++x&&(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p===t))break;return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||oe.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?se(function(e,n){var r,o=i(e,t),a=o.length;while(a--)e[r=O(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:se(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?se(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:se(function(e){return function(t){return oe(e,t).length>0}}),contains:se(function(e){return e=e.replace(Z,ee),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:se(function(e){return U.test(e||"")||oe.error("unsupported lang: "+e),e=e.replace(Z,ee).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Y.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:he(function(){return[0]}),last:he(function(e,t){return[t-1]}),eq:he(function(e,t,n){return[n<0?n+t:n]}),even:he(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:he(function(e,t,n){for(var r=n<0?n+t:n;++r1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function be(e,t,n){for(var r=0,i=t.length;r-1&&(o[l]=!(a[l]=f))}}else v=we(v===a?v.splice(h,v.length):v),i?i(null,a,v,u):L.apply(a,v)})}function Ce(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=me(function(e){return e===t},s,!0),f=me(function(e){return O(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u1&&xe(p),u>1&&ve(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u0,i=e.length>0,o=function(o,a,s,u,c){var f,h,y,v=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){h=0,a||f.ownerDocument===d||(p(f),s=!g);while(y=e[h++])if(y(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!y&&f)&&v--,o&&x.push(f))}if(v+=m,n&&m!==v){h=0;while(y=t[h++])y(x,b,a,s);if(o){if(v>0)while(m--)x[m]||b[m]||(b[m]=j.call(u));b=we(b)}L.apply(u,b),c&&!o&&b.length>0&&v+t.length>1&&oe.uniqueSort(u)}return c&&(T=E,l=w),x};return n?se(o):o}return s=oe.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=a(e)),n=t.length;while(n--)(o=Ce(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ee(i,r))).selector=e}return o},u=oe.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(Z,ee),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}o=V.needsContext.test(e)?0:u.length;while(o--){if(l=u[o],r.relative[c=l.type])break;if((f=r.find[c])&&(i=f(l.matches[0].replace(Z,ee),K.test(u[0].type)&&ge(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ve(u)))return L.apply(n,i),n;break}}}return(p||s(e,d))(i,t,!g,n,!t||K.test(e)&&ge(t.parentNode)||t),n},n.sortStable=b.split("").sort(D).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ue(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||le("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ue(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||le("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||le(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),oe}(e);w.find=E,w.expr=E.selectors,w.expr[":"]=w.expr.pseudos,w.uniqueSort=w.unique=E.uniqueSort,w.text=E.getText,w.isXMLDoc=E.isXML,w.contains=E.contains,w.escapeSelector=E.escape;var k=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&w(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},D=w.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var A=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,t,n){return g(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return u.call(t,e)>-1!==n}):w.filter(t,e,n)}w.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return 1===e.nodeType}))},w.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(w(e).filter(function(){for(t=0;t1?w.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&D.test(e)?w(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:L.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),A.test(i[1])&&w.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,q=w(r);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&w.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?w.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(w(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(w.uniqueSort(w.merge(this.get(),w(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}w.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return k(e,"parentNode")},parentsUntil:function(e,t,n){return k(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return k(e,"nextSibling")},prevAll:function(e){return k(e,"previousSibling")},nextUntil:function(e,t,n){return k(e,"nextSibling",n)},prevUntil:function(e,t,n){return k(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return N(e,"iframe")?e.contentDocument:(N(e,"template")&&(e=e.content||e),w.merge([],e.childNodes))}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=w.filter(r,i)),this.length>1&&(O[e]||w.uniqueSort(i),H.test(e)&&i.reverse()),this.pushStack(i)}});var M=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return w.each(e.match(M)||[],function(e,n){t[n]=!0}),t}w.Callbacks=function(e){e="string"==typeof e?R(e):w.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1){n=a.shift();while(++s-1)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?w.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l};function I(e){return e}function W(e){throw e}function $(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}w.extend({Deferred:function(t){var n=[["notify","progress",w.Callbacks("memory"),w.Callbacks("memory"),2],["resolve","done",w.Callbacks("once memory"),w.Callbacks("once memory"),0,"resolved"],["reject","fail",w.Callbacks("once memory"),w.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return w.Deferred(function(t){w.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t=o&&(r!==W&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(w.Deferred.getStackHook&&(c.stackTrace=w.Deferred.getStackHook()),e.setTimeout(c))}}return w.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:I,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:I)),n[2][3].add(a(0,e,g(r)?r:W))}).promise()},promise:function(e){return null!=e?w.extend(e,i):i}},o={};return w.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=w.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&($(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();while(n--)$(i[n],s(n),a.reject);return a.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;w.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&B.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},w.readyException=function(t){e.setTimeout(function(){throw t})};var F=w.Deferred();w.fn.ready=function(e){return F.then(e)["catch"](function(e){w.readyException(e)}),this},w.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--w.readyWait:w.isReady)||(w.isReady=!0,!0!==e&&--w.readyWait>0||F.resolveWith(r,[w]))}}),w.ready.then=F.then;function _(){r.removeEventListener("DOMContentLoaded",_),e.removeEventListener("load",_),w.ready()}"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(w.ready):(r.addEventListener("DOMContentLoaded",_),e.addEventListener("load",_));var z=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n)){i=!0;for(s in n)z(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,g(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(w(e),n)})),t))for(;s1,null,!0)},removeData:function(e){return this.each(function(){K.remove(this,e)})}}),w.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=J.get(e,t),n&&(!r||Array.isArray(n)?r=J.access(e,t,w.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),o=w._queueHooks(e,t),a=function(){w.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return J.get(e,n)||J.access(e,n,{empty:w.Callbacks("once memory").add(function(){J.remove(e,[t+"queue",n])})})}}),w.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]+)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&N(e,t)?w.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n-1)i&&i.push(o);else if(l=w.contains(o.ownerDocument,o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}!function(){var e=r.createDocumentFragment().appendChild(r.createElement("div")),t=r.createElement("input");t.setAttribute("type","radio"),t.setAttribute("checked","checked"),t.setAttribute("name","t"),e.appendChild(t),h.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="",h.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var be=r.documentElement,we=/^key/,Te=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ce=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function ke(){return!1}function Se(){try{return r.activeElement}catch(e){}}function De(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)De(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=ke;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return w().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=w.guid++)),e.each(function(){w.event.add(this,t,i,r,n)})}w.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.get(e);if(y){n.handler&&(n=(o=n).handler,i=o.selector),i&&w.find.matchesSelector(be,i),n.guid||(n.guid=w.guid++),(u=y.events)||(u=y.events={}),(a=y.handle)||(a=y.handle=function(t){return"undefined"!=typeof w&&w.event.triggered!==t.type?w.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(M)||[""]).length;while(l--)d=g=(s=Ce.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=w.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=w.event.special[d]||{},c=w.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&w.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),w.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.hasData(e)&&J.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(M)||[""]).length;while(l--)if(s=Ce.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){f=w.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||w.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)w.event.remove(e,d+t[l],n,r,!0);w.isEmptyObject(u)&&J.remove(e,"handle events")}},dispatch:function(e){var t=w.event.fix(e),n,r,i,o,a,s,u=new Array(arguments.length),l=(J.get(this,"events")||{})[t.type]||[],c=w.event.special[t.type]||{};for(u[0]=t,n=1;n=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n-1:w.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u\x20\t\r\n\f]*)[^>]*)\/>/gi,Ae=/\s*$/g;function Le(e,t){return N(e,"table")&&N(11!==t.nodeType?t:t.firstChild,"tr")?w(e).children("tbody")[0]||e:e}function He(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Oe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Pe(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(J.hasData(e)&&(o=J.access(e),a=J.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n1&&"string"==typeof y&&!h.checkClone&&je.test(y))return e.each(function(i){var o=e.eq(i);v&&(t[0]=y.call(this,i,o.html())),Re(o,t,n,r)});if(p&&(i=xe(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=w.map(ye(i,"script"),He)).length;f")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=w.contains(e.ownerDocument,e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||w.isXMLDoc(e)))for(a=ye(s),r=0,i=(o=ye(e)).length;r0&&ve(a,!u&&ye(e,"script")),s},cleanData:function(e){for(var t,n,r,i=w.event.special,o=0;void 0!==(n=e[o]);o++)if(Y(n)){if(t=n[J.expando]){if(t.events)for(r in t.events)i[r]?w.event.remove(n,r):w.removeEvent(n,r,t.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),w.fn.extend({detach:function(e){return Ie(this,e,!0)},remove:function(e){return Ie(this,e)},text:function(e){return z(this,function(e){return void 0===e?w.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Re(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Le(this,e).appendChild(e)})},prepend:function(){return Re(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Le(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(w.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return w.clone(this,e,t)})},html:function(e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w.htmlPrefilter(e);try{for(;n=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))),u}function et(e,t,n){var r=$e(e),i=Fe(e,t,r),o="border-box"===w.css(e,"boxSizing",!1,r),a=o;if(We.test(i)){if(!n)return i;i="auto"}return a=a&&(h.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===w.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],a=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),a,r,i)+"px"}w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Fe(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=G(t),u=Xe.test(t),l=e.style;if(u||(t=Je(s)),a=w.cssHooks[t]||w.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"==(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=ue(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(w.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=G(t);return Xe.test(t)||(t=Je(s)),(a=w.cssHooks[t]||w.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Fe(e,t,r)),"normal"===i&&t in Ve&&(i=Ve[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n)return!ze.test(w.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):se(e,Ue,function(){return et(e,t,r)})},set:function(e,n,r){var i,o=$e(e),a="border-box"===w.css(e,"boxSizing",!1,o),s=r&&Ze(e,t,r,a,o);return a&&h.scrollboxSize()===o.position&&(s-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),s&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=w.css(e,t)),Ke(e,n,s)}}}),w.cssHooks.marginLeft=_e(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Fe(e,"marginLeft"))||e.getBoundingClientRect().left-se(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(w.cssHooks[e+t].set=Ke)}),w.fn.extend({css:function(e,t){return z(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;a1)}});function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}w.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||w.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(w.cssNumber[n]?"":"px")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=w.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=w.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){w.fx.step[e.prop]?w.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[w.cssProps[e.prop]]&&!w.cssHooks[e.prop]?e.elem[e.prop]=e.now:w.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},w.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},w.fx=tt.prototype.init,w.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,w.fx.interval),w.fx.tick())}function st(){return e.setTimeout(function(){nt=void 0}),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(pt.tweeners[t]||[]).concat(pt.tweeners["*"]),o=0,a=i.length;o1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})}}),w.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?w.prop(e,t,n):(1===o&&w.isXMLDoc(e)||(i=w.attrHooks[t.toLowerCase()]||(w.expr.match.bool.test(t)?dt:void 0)),void 0!==n?null===n?void w.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=w.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&N(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(M);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),dt={set:function(e,t,n){return!1===t?w.removeAttr(e,n):e.setAttribute(n,n),n}},w.each(w.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||w.find.attr;ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=ht[a],ht[a]=i,i=null!=n(e,t,r)?a:null,ht[a]=o),i}});var gt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;w.fn.extend({prop:function(e,t){return z(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[w.propFix[e]||e]})}}),w.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&w.isXMLDoc(e)||(t=w.propFix[t]||t,i=w.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):gt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),h.optSelected||(w.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});function vt(e){return(e.match(M)||[]).join(" ")}function mt(e){return e.getAttribute&&e.getAttribute("class")||""}function xt(e){return Array.isArray(e)?e:"string"==typeof e?e.match(M)||[]:[]}w.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).addClass(e.call(this,t,mt(this)))});if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).removeClass(e.call(this,t,mt(this)))});if(!arguments.length)return this.attr("class","");if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])while(r.indexOf(" "+o+" ")>-1)r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){w(this).toggleClass(e.call(this,n,mt(this),t),t)}):this.each(function(){var t,i,o,a;if(r){i=0,o=w(this),a=xt(e);while(t=a[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else void 0!==e&&"boolean"!==n||((t=mt(this))&&J.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":J.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&(" "+vt(mt(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;w.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,w(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=w.map(i,function(e){return null==e?"":e+""})),(t=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=w.valHooks[i.type]||w.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(bt,""):null==n?"":n}}}),w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return null!=t?t:vt(w.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=w.inArray(w(e).val(),t)>-1}},h.checkOn||(w.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var wt=/^(?:focusinfocus|focusoutblur)$/,Tt=function(e){e.stopPropagation()};w.extend(w.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,v=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!wt.test(m+w.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,t=t[w.expando]?t:new w.Event(m,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:w.makeArray(n,[t]),d=w.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!y(i)){for(l=d.delegateType||m,wt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(i.ownerDocument||r)&&v.push(u.defaultView||u.parentWindow||e)}a=0;while((s=v[a++])&&!t.isPropagationStopped())h=s,t.type=a>1?l:d.bindType||m,(p=(J.get(s,"events")||{})[t.type]&&J.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&Y(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(v.pop(),n)||!Y(i)||c&&g(i[m])&&!y(i)&&((u=i[c])&&(i[c]=null),w.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,Tt),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,Tt),w.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=w.extend(new w.Event,n,{type:e,isSimulated:!0});w.event.trigger(r,null,t)}}),w.fn.extend({trigger:function(e,t){return this.each(function(){w.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return w.event.trigger(e,t,n,!0)}}),h.focusin||w.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){w.event.simulate(t,e.target,w.event.fix(e))};w.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=J.access(r,t);i||r.addEventListener(e,n,!0),J.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=J.access(r,t)-1;i?J.access(r,t,i):(r.removeEventListener(e,n,!0),J.remove(r,t))}}});var Ct=e.location,Et=Date.now(),kt=/\?/;w.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||w.error("Invalid XML: "+t),n};var St=/\[\]$/,Dt=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function jt(e,t,n,r){var i;if(Array.isArray(t))w.each(t,function(t,i){n||St.test(e)?r(e,i):jt(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)jt(e+"["+i+"]",t[i],n,r)}w.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!w.isPlainObject(e))w.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=w(this).val();return null==n?null:Array.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var qt=/%20/g,Lt=/#.*$/,Ht=/([?&])_=[^&]*/,Ot=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Mt=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Bt=r.createElement("a");Bt.href=Ct.href;function Ft(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(M)||[];if(g(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function _t(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,w.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function zt(e,t){var n,r,i=w.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&w.extend(!0,e,r),e}function Xt(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Ut(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Pt.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":w.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,w.ajaxSettings),t):zt(w.ajaxSettings,e)},ajaxPrefilter:Ft(It),ajaxTransport:Ft(Wt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=w.ajaxSetup({},n),g=h.context||h,y=h.context&&(g.nodeType||g.jquery)?w(g):w.event,v=w.Deferred(),m=w.Callbacks("once memory"),x=h.statusCode||{},b={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){s={};while(t=Ot.exec(a))s[t[1].toLowerCase()]=t[2]}t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(v.promise(E),h.url=((t||h.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(M)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Bt.protocol+"//"+Bt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=w.param(h.data,h.traditional)),_t(It,h,n,E),c)return E;(f=w.event&&h.global)&&0==w.active++&&w.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Mt.test(h.type),o=h.url.replace(Lt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(qt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Ht,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et+++d),h.url=o+d),h.ifModified&&(w.lastModified[o]&&E.setRequestHeader("If-Modified-Since",w.lastModified[o]),w.etag[o]&&E.setRequestHeader("If-None-Match",w.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+$t+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=_t(Wt,h,n,E)){if(E.readyState=1,f&&y.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,b,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=Xt(h,E,r)),b=Ut(h,b,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(w.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(w.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,l=!(d=b.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?v.resolveWith(g,[p,C,E]):v.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&y.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(y.trigger("ajaxComplete",[E,h]),--w.active||w.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,t){return w.get(e,void 0,t,"script")}}),w.each(["get","post"],function(e,t){w[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),w.ajax(w.extend({url:e,type:t,dataType:i,data:n,success:r},w.isPlainObject(e)&&e))}}),w._evalUrl=function(e){return w.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},w.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=w(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){w(this).wrapInner(e.call(this,t))}):this.each(function(){var t=w(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){w(this).replaceWith(this.childNodes)}),this}}),w.expr.pseudos.hidden=function(e){return!w.expr.pseudos.visible(e)},w.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=w.ajaxSettings.xhr();h.cors=!!Gt&&"withCredentials"in Gt,h.ajax=Gt=!!Gt,w.ajaxTransport(function(t){var n,r;if(h.cors||Gt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),w.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return w.globalEval(e),e}}}),w.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),w.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(i,o){t=w("