{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# doc2vec\n", "\n", "This is an experimental code developed by Tomas Mikolov found and [published on the word2vec Google group](https://groups.google.com/d/msg/word2vec-toolkit/Q49FIrNOQRo/J6KG8mUj45sJ).\n", "\n", "The input format for `doc2vec` is still one big text document but every line should be one document prepended with an unique id, for example:\n", "\n", "```\n", "_*0 This is sentence 1\n", "_*1 This is sentence 2\n", "```\n", "\n", "### Requirements\n", "\n", "This notebook requires [`nltk`](http://www.nltk.org/)\n", "\n", "Download some data: http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz.\n", "\n", "You could use `make test-data` from the root of the repo.\n", "\n", "## Preprocess\n", "\n", "Merge data into one big document with an id per line and do some basic preprocessing: word tokenizer." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import os\n", "import nltk" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "directories = ['train/pos', 'train/neg', 'test/pos', 'test/neg', 'train/unsup']" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "input_file = open('../data/alldata.txt', 'w')" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "id_ = 0\n", "for directory in directories:\n", " rootdir = os.path.join('../data/aclImdb', directory)\n", " for subdir, dirs, files in os.walk(rootdir):\n", " for file_ in files:\n", " with open(os.path.join(subdir, file_), \"r\") as f:\n", " doc_id = \"_*%i\" % id_\n", " id_ = id_ + 1\n", "\n", " text = f.read()\n", " text = text\n", " tokens = nltk.word_tokenize(text)\n", " doc = \" \".join(tokens).lower()\n", " doc = doc.encode(\"ascii\", \"ignore\")\n", " input_file.write(\"%s %s\\n\" % (doc_id, doc))" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "input_file.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## doc2vec" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import word2vec" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word2vec.doc2vec('../data/alldata.txt', '../data/doc2vec-vectors.bin', cbow=0, size=100, window=10, negative=5,\n", " hs=0, sample='1e-4', threads=12, iter_=20, min_count=1, binary=True, verbose=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Prediction\n", "\n", "Is possible to load the vectors using the same wordvectors class as a regular word2vec binary file." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import word2vec" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "model = word2vec.load('../data/doc2vec-vectors.bin')" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(363652, 100)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model.vectors.shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The documents vector are going to be identified by the id we used in the preprocesing section, for example document 1 is going to have vector:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 0.15458781, 0.05329125, -0.03372733, -0.03253617, -0.00038198,\n", " 0.01859742, 0.05822669, 0.08649707, 0.07116864, 0.01571589,\n", " 0.11401868, 0.05802745, -0.03446389, -0.05136882, -0.03741959,\n", " 0.03825757, 0.03826223, 0.06828724, 0.05144465, -0.02519033,\n", " -0.02553019, -0.13064705, -0.01241815, 0.06572731, 0.0361409 ,\n", " 0.06780364, -0.11406382, 0.03698812, 0.01645933, 0.04006057,\n", " -0.06411161, 0.10451728, -0.09016737, 0.0612823 , 0.05084847,\n", " 0.05336419, 0.13584702, -0.05651987, 0.01329237, -0.20875289,\n", " -0.08468074, 0.10479708, 0.05787989, 0.13176955, -0.01580021,\n", " 0.07367507, -0.09352259, -0.13971043, -0.24871282, -0.14094608,\n", " 0.04577528, 0.12431064, -0.05354084, 0.14227368, -0.11196741,\n", " 0.03350607, -0.01999633, -0.07860398, 0.02664598, -0.0592974 ,\n", " -0.07686727, -0.05597671, -0.06345078, -0.27290845, -0.06400879,\n", " 0.00619202, -0.01699482, -0.05217196, 0.17153341, 0.12772463,\n", " -0.02238818, 0.09656674, 0.09250097, -0.18347315, -0.15046608,\n", " -0.04235512, -0.15838784, 0.03597225, -0.01584246, 0.00568255,\n", " 0.0409179 , 0.02537416, 0.06123869, 0.0961483 , -0.12116033,\n", " 0.07526031, 0.0303142 , -0.01561208, 0.36425424, -0.16918449,\n", " 0.07423471, 0.14127608, 0.00530258, -0.10363475, 0.00953067,\n", " -0.04992943, 0.1713592 , 0.21640711, -0.00298326, 0.05985325])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model['_*1']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can ask for similarity words or documents on document `1`" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "indexes, metrics = model.similar('_*1')" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[('_*2351', 0.8519178427298584),\n", " ('imagery.an', 0.8397190257038456),\n", " ('_*58565', 0.8342486893807792),\n", " ('_*35569', 0.8274130976031872),\n", " ('_*79830', 0.8268153781216658),\n", " ('_*37088', 0.8245519264554979),\n", " ('b\"witness', 0.8239716809480113),\n", " (\"b'ghost\", 0.822800405312356),\n", " (\"l'anticristo\", 0.8222915811568171),\n", " ('_*38763', 0.8189633692215181)]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model.generate_response(indexes, metrics).tolist()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now its we just need to matching the id to the data created on the preprocessing step" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.6" } }, "nbformat": 4, "nbformat_minor": 4 }