{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["# 2A.i - Strat\u00e9gies et grandes matrices en m\u00e9moire\n", "\n", "El\u00e9ments de r\u00e9flexion autour des jeux de donn\u00e9es trop grands pour tenir en m\u00e9moire."]}, {"cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [{"data": {"text/html": ["
run previous cell, wait for 2 seconds
\n", ""], "text/plain": [""]}, "execution_count": 2, "metadata": {}, "output_type": "execute_result"}], "source": ["from jyquickhelper import add_notebook_menu\n", "add_notebook_menu()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Introduction\n", "\n", "Les ordinateurs portables ont en moyenne 8 Go de m\u00e9moire, les machines de bureau peuvent aller bien au-del\u00e0, monter jusqu'\u00e0 1 To de m\u00e9moire vive. 8Go suffisent pour la plupart des usages. Que faire quand cela ne suffit pas ? Chaque section propose une direction."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Echantillon al\u00e9atoire\n", "\n", "C'est le premier r\u00e9flexe. On regarde les donn\u00e9es avec un \u00e9chantillon al\u00e9atoire qui tient en m\u00e9moire et avec lequel les calculs prennent un temps raisonnable."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Changer de type num\u00e9rique"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Beaucoup de librairies de machine learning utilise des [float](https://en.wikipedia.org/wiki/Floating_point) et non [double](https://en.wikipedia.org/wiki/Double-precision_floating-point_format). La pr\u00e9cision est moindre mais peut n'a-t-on besoin de cette pr\u00e9cision pour les calculs. Il en va de m\u00eame pour les entiers. Si on sait qu'une variable prend ses valeurs entre 0 et 255, un octet pour repr\u00e9senter chaque entier."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Matrice creuse ou sparse\n", "\n", "Beaucoup de grandes matrices sont creuses : la plupart des coefficients sont nulles. Cela est souvent le cas pour les [matrice d'adjacence](https://fr.wikipedia.org/wiki/Matrice_d%27adjacence) des graphes. Dans ce cas, il est avantageux de ne stocker que les coefficients non nuls et d'utiliser les op\u00e9rations matricielles ad\u00e9quates de sorte que les z\u00e9ros ne soient jamais pr\u00e9sents en m\u00e9moire.\n", "\n", "* [Sparse matrices](http://docs.scipy.org/doc/scipy/reference/sparse.html)\n", "\n", "On ne stocke en m\u00e9moire que les coefficients non nuls et leurs coordonn\u00e9es. C'est une fa\u00e7on de compresser l'information. Il existe plusieurs formats. Le plus usit\u00e9 est le format [CSR](https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_row_.28CSR.2C_CRS_or_Yale_format.29) pour *Compressed sparse row*. Ce n'est pas le seul. Pour une matrice sym\u00e9trique, on ne m\u00e9morisera que la moiti\u00e9 des coefficients. Il n'existe pas de meilleur format en g\u00e9n\u00e9ral mais un meilleur format adapt\u00e9 \u00e0 un usage."]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 1 : CSR et CSC\n", "\n", "Mesurer le temps que prend une multiplication matricielle avec les trois formats dense, [CSC](http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.csc_matrix.html#scipy.sparse.csc_matrix) et [CSR](http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.csr_matrix.html#scipy.sparse.csr_matrix). Il faut produire une matrice 3x3 avec des matrices carr\u00e9es et non carr\u00e9es, dense ou sparse..."]}, {"cell_type": "code", "execution_count": 2, "metadata": {"collapsed": true}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 2 : sparse dataframe\n", "\n", "pandas propose une version sparse des dataframes. Il suffit d'appeler la m\u00e9thode [to_sparse](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_sparse.html?highlight=to_sparse#pandas.DataFrame.to_sparse). Mesurer le gain en m\u00e9mroire pour diff\u00e9rents dataframes."]}, {"cell_type": "code", "execution_count": 3, "metadata": {"collapsed": true}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## SQL\n", "\n", "Certains calculs ne n\u00e9cessitent d'avoir toutes les donn\u00e9es en m\u00e9moire. C'est le cas d'une moyenne et typiquement de tout calcul s'appuyant sur une logique [SQL](https://fr.wikipedia.org/wiki/Structured_Query_Language) ou Map/Reduce. On place les donn\u00e9es dans une base de donn\u00e9es SQL. On manipule les donn\u00e9es en SQL, on ne charge en m\u00e9moire que ce qui est n\u00e9cessaire.\n", "\n", "* [sqlite3](https://docs.python.org/3/library/sqlite3.html)\n", "* [Python et la logique SQL](http://www.xavierdupre.fr/app/ensae_teaching_cs/helpsphinx/notebooks/td2a_eco_sql.html)\n", "* [Donn\u00e9es non structur\u00e9es, programmation fonctionnelle](http://www.xavierdupre.fr/app/ensae_teaching_cs/helpsphinx/notebooks/seance_5_intro_et_json.html)\n", "* [Donn\u00e9es multidimensionnelles SQL](http://www.xavierdupre.fr/app/actuariat_python/helpsphinx/notebooks/seance5_sql_multidimensionnelle_enonce.html)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 3 : constuire une base donn\u00e9es SQL \u00e0 partir de plusieurs dataframe."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Format compress\u00e9\n", "\n", "Les donn\u00e9es sont compress\u00e9es pour prendre moins de place. Les calculs n\u00e9cessitent alors que les matrices soient d\u00e9compress\u00e9s avant les calculs puis les r\u00e9sultats compress\u00e9s. Le module [h5py](http://www.h5py.org/) est couramment utilis\u00e9 et souvent via un autre module qui masque le fait que les donn\u00e9es sont compress\u00e9es. [blosc](http://blosc.org/) est un autre module de compression, voir aussi [python-blosc](http://python-blosc.blosc.org/tutorial.html).\n", "\n", "* [pytables](http://www.pytables.org/) g\u00e8re des bases de donn\u00e9es enregistr\u00e9es au format [HDF5](https://en.wikipedia.org/wiki/Hierarchical_Data_Format), fonctionne avec [blosc](http://blosc.org/).\n", "* [zarr](http://zarr.readthedocs.io/en/latest/) : utilise [blosc](http://blosc.org/) pour compresser les donn\u00e9es, propose des op\u00e9rations pour cr\u00e9er facilement des matrices compress\u00e9es.\n", "* [wendelin.core](https://pypi.python.org/pypi/wendelin.core) : API pour faire des calculs matriciels sur des matrices stock\u00e9es en m\u00e9moire et sur disque"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 4 : \u00e9crire un exemple de multiplication matriciel avec pytables et zarr"]}, {"cell_type": "code", "execution_count": 4, "metadata": {"collapsed": true}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## Librairies d\u00e9di\u00e9es\n", "\n", "Certaines structures de donn\u00e9es sont r\u00e9currentes et certaines librairies ont \u00e9t\u00e9 impl\u00e9ment\u00e9es pour les manipuler.\n", "\n", "* [xarray](https://pypi.python.org/pypi/xarray) : pour manipuler les tableaux en plusieurs dimensions, s'appuie sur numpy\n", "* [dynd-python](https://github.com/libdynd/dynd-python) : aussi pour manipuler les tableaux en plusieurs dimensions mais impl\u00e9ment\u00e9 en C++\n", "* [cubes](https://pythonhosted.org/cubes/) : toujours tableaux multidimensionnels mais stock\u00e9s via une base de donn\u00e9es\n", "* [blist](https://pypi.python.org/pypi/blist) : impl\u00e9mente de large liste plus efficace que le type list\n", "* [datashader](https://pypi.python.org/pypi/datashader) : afficher rapidement des graphes actifs (javascript) avec des millions d'observations\n"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 5 : comparer les modules xarray, dynd-python, cubes, blist, datashader"]}, {"cell_type": "code", "execution_count": 5, "metadata": {"collapsed": true}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## Parall\u00e9lisation\n", "\n", "C'est une option pas toujours \u00e9vidente \u00e0 mettre en place car elle implique d'\u00e9crire diff\u00e9remment les algorithmes.\n", "\n", "* [dask](http://dask.pydata.org/en/latest/) : une sorte de pandas parall\u00e9lis\u00e9, ne fait pas tout ce qui propose pandas, seulement ce qui est parall\u00e9lisable\n", "* [pystorm](https://pypi.python.org/pypi/pystorm) : interface pour [storm](http://storm.apache.org/)\n", "* [rx](https://github.com/ReactiveX/RxPY) : it\u00e9rateurs parall\u00e9lis\u00e9s avec une syntaxe tr\u00e8s proche de [LINQ](https://msdn.microsoft.com/en-us/library/mt693024.aspx)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 6 : essayer un exemple avec chacun des trois modules"]}, {"cell_type": "code", "execution_count": 6, "metadata": {"collapsed": true}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## S\u00e9rialisation\n", "\n", "La s\u00e9rialisation permet de gagner du temps lors de l'\u00e9criture et la lecture d'objet. Les objets sont enregistr\u00e9s dans un format tr\u00e8s proche de celui qu'il a en m\u00e9moire. Le chargement des donn\u00e9es est tr\u00e8s rapide. Pour un dataframe, le fait de s\u00e9rialiser \u00e9vite toutes les op\u00e9rations de conversion des nombres au format num\u00e9rique. Ce processus est tr\u00e8s pratique pour les gros dataframe.\n", "\n", "* [pickle](https://docs.python.org/3/library/pickle.html) : module faisant partie des mdoules standard de Python\n", "* [dill](https://pypi.python.org/pypi/dill) : extension de pickle"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 7 : s\u00e9rialiser un dataframe"]}, {"cell_type": "code", "execution_count": 7, "metadata": {"collapsed": true}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 8 : peut-on s\u00e9rialiser un dataframe de dask ?"]}, {"cell_type": "code", "execution_count": 8, "metadata": {"collapsed": true}, "outputs": [], "source": []}], "metadata": {"kernelspec": {"display_name": "Python 3", "language": "python", "name": "python3"}, "language_info": {"codemirror_mode": {"name": "ipython", "version": 3}, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.1"}}, "nbformat": 4, "nbformat_minor": 2}