Apprendimento automatico e Reti Neurali - pagina 67

 

2.5 Miglioramento dei k-vicini più vicini (L02: Metodi del vicino più vicino)



2.5 Miglioramento dei k-vicini più vicini (L02: Metodi del vicino più vicino)

In questo video, approfondiremo l'argomento del miglioramento dell'algoritmo K-nearest neighbors attraverso alcune modifiche e la considerazione degli iperparametri. Nel video precedente, abbiamo discusso l'uso di una coda prioritaria come struttura dati per migliorare l'efficienza della ricerca dei vicini più vicini. Questa coda prioritaria aiuta a evitare di cercare l'intero set di addestramento per ogni nuovo vicino.

Ora, esploriamo un altro approccio per migliorare le prestazioni computazionali dell'algoritmo K-nearest neighbors utilizzando strutture di dati di partizionamento dello spazio. Una di queste strutture di dati è l'heap, che funge da struttura di partizionamento dello spazio per accelerare il processo di ricerca sugli esempi di addestramento. Dividendo il set di dati in sottoinsiemi all'interno della struttura dei dati, possiamo ridurre al minimo la necessità di calcoli della distanza per ogni punto dati di addestramento.

Un metodo di partizionamento dello spazio è chiamato bucket. Ciò comporta la divisione del set di dati in sottoinsiemi o bucket in base a criteri specifici, ad esempio bucket di uguali dimensioni o limiti definiti dalle misurazioni delle funzionalità. In questo modo, possiamo evitare di cercare l'intero set di addestramento e concentrarci solo sui punti rilevanti all'interno di un particolare bucket quando cerchiamo i vicini di un punto di query. Questa ottimizzazione migliora notevolmente l'efficienza del processo di ricerca.

Un'altra tecnica di partizionamento dello spazio è l'albero KD, che costruisce ipercubi per dividere il set di dati. Questo metodo differisce dal bucketing ma condivide l'obiettivo di migliorare l'efficienza della ricerca riducendo il numero di calcoli della distanza. Gli alberi KD sono particolarmente adatti per set di dati con un gran numero di funzionalità.

Allo stesso modo, l'algoritmo dell'albero delle palle crea ipersfere come partizioni spaziali. La scelta tra alberi KD e alberi palla dipende dalle caratteristiche del set di dati. Per i set di dati con un'elevata dimensionalità, viene spesso preferito l'algoritmo dell'albero delle palle. Vale la pena notare che la libreria di apprendimento automatico scikit-learn, uno strumento ampiamente utilizzato, offre diverse opzioni per l'algoritmo del classificatore del vicino più vicino K, selezionando automaticamente l'algoritmo di partizionamento dello spazio più efficiente in base al set di dati. Tuttavia, se lo desideri, puoi ignorare manualmente questa impostazione.

Inoltre, possiamo migliorare le prestazioni dei vicini K più vicini impiegando tecniche di riduzione della dimensionalità. La riduzione della dimensionalità è disponibile in due versioni: estrazione delle caratteristiche e selezione delle caratteristiche. L'estrazione delle caratteristiche comporta la trasformazione o la combinazione di caratteristiche esistenti per creare una rappresentazione dei dati di dimensioni inferiori. D'altra parte, la selezione delle funzionalità comporta la selezione di un sottoinsieme delle funzionalità disponibili senza crearne di nuove. Riducendo il numero di caratteristiche, possiamo ridurre il costo computazionale dei calcoli della distanza e potenzialmente migliorare l'efficienza dell'algoritmo. Inoltre, i set di dati ad alta dimensione spesso soffrono della maledizione della dimensionalità, che può portare a scarse prestazioni di generalizzazione a causa dell'overfitting. Pertanto, la riduzione della dimensionalità può anche aiutare ad alleviare questo problema.

Per ottimizzare le prestazioni computazionali dei vicini K-più vicini, possiamo esplorare tecniche di modifica o sfoltimento. La potatura comporta la rimozione di punti dati non necessari dal set di addestramento senza influire sul limite decisionale. Eliminando i punti ridondanti, possiamo ridurre il numero di confronti e calcoli di distanza, rendendo l'algoritmo più efficiente. Allo stesso modo, la creazione di prototipi implica la sostituzione di una regione densa di punti dati di addestramento con un singolo punto rappresentativo. Questa strategia riduce i requisiti di spazio di archiviazione preservando l'accuratezza predittiva dell'algoritmo.

Inoltre, l'ottimizzazione degli iperparametri gioca un ruolo cruciale nel migliorare le prestazioni predittive dell'algoritmo K-nearest neighbors. Gli iperparametri sono impostazioni sintonizzabili che influiscono sul comportamento dell'algoritmo ma non vengono apprese dai dati di addestramento. Includono il valore di K (il numero di vicini da considerare), il ridimensionamento delle caratteristiche, la misura della distanza utilizzata e lo schema di ponderazione per il calcolo della distanza. La scelta di valori appropriati per questi iperparametri può influire in modo significativo sulle prestazioni dell'algoritmo. Tuttavia, è essenziale prestare attenzione ed evitare di adattare eccessivamente il modello ai dati di addestramento.

Sfruttando le strutture di dati di partizionamento dello spazio, impiegando tecniche di riduzione della dimensionalità, applicando metodi di modifica e potatura e ottimizzando gli iperparametri, possiamo migliorare sia le prestazioni computazionali che quelle predittive dell'algoritmo K-vicini più vicini.

2.5 Improving k-nearest neighbors (L02: Nearest Neighbor Methods)
2.5 Improving k-nearest neighbors (L02: Nearest Neighbor Methods)
  • 2020.09.08
  • www.youtube.com
This video summarizes some of the common tricks for making k-nearest neighbors more efficient in terms of computational performance and predictive performanc...
 

2.6 K-Vicini più vicini in Python (L02: Metodi del vicino più vicino)



2.6 K-Vicini più vicini in Python (L02: Metodi del vicino più vicino)

Dopo un'esauriente discussione sui vicini K-più vicini, il testo procede presentando un esempio Python che mostra l'implementazione dei vicini K-più vicini utilizzando la popolare libreria scikit-learn. L'autore riconosce che non tutti gli aspetti possono essere immediatamente chiari e assicura ai lettori che le lezioni future approfondiranno Python, NumPy e scikit-learn. Tuttavia, l'esempio fornito funge da teaser per offrire una prospettiva dall'alto verso il basso su come funzionano questi strumenti.

Per supportare l'esempio di implementazione, l'autore fa riferimento a un sito Web in cui i lettori possono trovare esempi di codice. Inoltre, l'autore spiega il processo di download di un repository da GitHub utilizzando il file zip o clonandolo. Sottolineando l'importanza di GitHub come strumento del mondo reale, l'autore suggerisce che avere un profilo GitHub e condividere progetti può essere vantaggioso per mostrare il proprio lavoro a potenziali datori di lavoro.

Il testo procede fornendo istruzioni dettagliate su come clonare un repository utilizzando il collegamento GitHub e il comando "git clone". Pur riconoscendo che il processo può variare leggermente per gli utenti Windows, l'autore consiglia di cercare tutorial o assistenza dal TA (assistente didattico). Una volta che il repository è stato clonato con successo, l'autore indica ai lettori di navigare nella cartella e spiega che è possibile ottenere gli aggiornamenti utilizzando il comando "git pull".

Passando agli esempi di codice, l'autore dimostra l'apertura di un Jupyter Notebook, in particolare Jupyter Lab, e l'esecuzione dei comandi passo dopo passo. Per evitare di sovraccaricare i lettori, l'autore sottolinea l'importanza di cancellare gli output dopo ogni esecuzione. Inoltre, l'autore menziona l'utilità dell'estensione filigrana in Jupyter Notebooks, che visualizza le versioni dei pacchetti software utilizzati. Queste informazioni aiutano nella risoluzione dei problemi e garantiscono la replicabilità dei risultati. Pacchetti essenziali come Pandas, NumPy, Matplotlib e scikit-learn vengono installati per facilitare l'implementazione.

Successivamente, l'autore carica il set di dati Iris da un file CSV e mostra l'uso di comandi come "testa" e "coda" per visualizzare in anteprima il set di dati. I dati vengono caricati in un DataFrame Pandas utilizzando la funzione "read_csv". Pur osservando che l'apprendimento automatico utilizza in genere gli array NumPy, l'autore sottolinea che scikit-learn supporta anche DataFrames. Per illustrare ciò, l'autore fornisce un esempio di estrazione di colonne specifiche dal DataFrame per creare un array NumPy. La forma dell'array, che indica il numero di esempi e funzioni di addestramento, viene visualizzata utilizzando il comando "shape".

Il testo delinea una serie di passaggi che costituiscono un flusso di lavoro di apprendimento automatico utilizzando Python e la libreria scikit-learn. Ecco un riepilogo dettagliato di questi passaggi:

  1. Rimescolamento di indici ed etichette: l'autore avvia il flusso di lavoro discutendo il processo di rimescolamento di indici ed etichette in un set di dati. Lo scopo dello shuffling è randomizzare l'ordine dei punti dati, assicurando che ogni etichetta corrisponda alla riga corretta nella matrice delle caratteristiche.

  2. Divisione del set di dati: il set di dati è suddiviso in un set di addestramento e un set di test. L'autore seleziona manualmente i primi 105 esempi per il training set e riserva i restanti 45 esempi per il test set. Questa divisione è fondamentale per valutare le prestazioni del modello di machine learning.

  3. Introduzione a scikit-learn e al set di dati Iris: l'autore introduce la libreria scikit-learn, in particolare l'implementazione del set di dati Iris e la funzione "train_test_split". Il set di dati Iris è un set di dati popolare ampiamente utilizzato per le attività di classificazione. La funzione "train_test_split" rimescola automaticamente il set di dati e lo suddivide nelle proporzioni specificate per l'addestramento e il test.

  4. Visualizzazione utilizzando una matrice di grafici a dispersione: l'autore fornisce una comoda funzione chiamata "matrice di grafici a dispersione" per visualizzare il set di dati. Questa funzione utilizza la libreria matplotlib per creare una matrice di grafici a dispersione con istogrammi visualizzati sulla diagonale. La matrice del grafico a dispersione rappresenta visivamente le relazioni tra le diverse funzionalità nel set di dati.

  5. Dimostrazione della matrice del grafico a dispersione: l'autore dimostra l'utilizzo della matrice del grafico a dispersione tracciando il set di dati Iris. Diversi colori sono assegnati per rappresentare diverse classi di fiori. In particolare, l'autore sottolinea che caratteristiche specifiche, come la lunghezza e la larghezza dei petali, sono particolarmente utili per distinguere tra diverse classi di fiori.

  6. Introduzione al classificatore k-nearest neighbors (k-NN): l'autore procede spiegando il classificatore k-nearest neighbors (k-NN), che è un semplice algoritmo che classifica i punti dati in base alla loro vicinanza ai punti dati vicini. Per istanziare il classificatore k-NN, l'autore crea un oggetto con tre vicini.

  7. Adattamento del classificatore k-NN: il classificatore k-NN viene adattato al set di addestramento utilizzando il metodo "fit". Questo passaggio esegue il training del modello utilizzando i dati di training forniti.

  8. Previsione sul set di test: l'autore utilizza il classificatore k-NN adattato per fare previsioni sul set di test utilizzando il metodo "predict". Le previsioni sono memorizzate in una variabile chiamata "pred".

  9. Valutazione delle prestazioni: per valutare le prestazioni del modello, l'autore confronta le etichette previste (memorizzate in "pred") con le vere etichette del set di test (memorizzate in "y_test"). Calcolando il numero di previsioni corrette, è possibile determinare l'accuratezza del modello sul set di test.

  10. Conclusione e ulteriore esplorazione: la conferenza si conclude incoraggiando i lettori a esplorare la documentazione di scikit-learn per ulteriori informazioni sull'algoritmo k-nearest neighbors e le sue varie opzioni. Inoltre, l'autore pone una domanda ai lettori riguardo alla metrica di distanza predefinita utilizzata dal classificatore k-NN e suggerisce un esercizio per indagare e discutere questo aspetto.

La conferenza fornisce una spiegazione completa di vari argomenti, tra cui il concetto di K-nearest neighbors, un'implementazione di esempio utilizzando la libreria scikit-learn, linee guida per il download e la clonazione di repository da GitHub, un'introduzione a Jupyter Notebook e Jupyter Lab, caricamento di un set di dati in un DataFrame Pandas e dimostrando l'estrazione di colonne e la conversione in matrici NumPy.

2.6 K-nearest neighbors in Python (L02: Nearest Neighbor Methods)
2.6 K-nearest neighbors in Python (L02: Nearest Neighbor Methods)
  • 2020.09.10
  • www.youtube.com
In this video, we are talking about using k-nearest neighbors in Python using scikit-learn. Jupyter Notebook: https://github.com/rasbt/stat451-machine-learni...
 

3.1 (Facoltativo) Panoramica di Python



3.1 (Facoltativo) Panoramica di Python

Spero che stiate trascorrendo una settimana fantastica finora e che vi stiate godendo le lezioni. Oggi voglio discutere alcuni argomenti importanti trattati nelle recenti lezioni.

In primo luogo, abbiamo tenuto una lezione sul miglioramento di Canaan, seguita da una lezione sull'implementazione dei parenti in Python usando l'apprendimento psichico. Sulla base del tuo feedback dall'introduzione per conoscere il tuo quiz, ho scoperto che la maggior parte di voi ha un background di programmazione o ha già frequentato un corso di programmazione. Questa è un'ottima notizia perché ti sarà molto utile in questo corso. Tuttavia, ho notato che solo circa la metà di voi ha una solida esperienza con Python. Pertanto, prima di immergerci nell'informatica scientifica con Python ed esplorare l'apprendimento psichico in modo più dettagliato, ho pensato che sarebbe stato utile fornire assistenza nella configurazione di Python per coloro che sono nuovi. Ciò assicurerà che la prossima lezione si svolga senza intoppi per tutti.

Su una nota più leggera, mi è davvero piaciuto leggere dei tuoi hobby preferiti. Sembra che molti di voi condividano il mio amore per le attività all'aria aperta come lo sci di fondo, la corsa e l'escursionismo. Trascorrere del tempo nella natura è davvero rinfrescante, anche se capisco che i giorni di pioggia e i lunghi inverni possono limitare queste opportunità. Alcuni di voi hanno anche accennato al proprio interesse per i videogiochi, con uno studente che ha persino menzionato la serie di Zelda. Devo ammettere che anche io sono un grande fan della serie e mi diverto a giocarci durante i nevosi giorni di Natale o dopo una giornata impegnativa per rilassarmi.

Andando avanti, come promesso, la lezione di oggi sarà facoltativa. Se hai già una solida esperienza con Python e hai configurato Python sul tuo computer, puoi saltare i seguenti tre video. Tuttavia, se sei nuovo in Python o hai bisogno di assistenza per configurarlo, ti consiglio di guardarli. Questi video ti forniranno motivazione e consigli pratici basati sulla mia esperienza con Python. È importante notare che non è necessario essere un programmatore esperto per utilizzare Python in questo corso. Ci concentreremo sulle basi necessarie per l'apprendimento automatico e imparerai di più man mano che progrediamo.

La prossima settimana avremo il nostro primo vero compito a casa, in cui implementerai un algoritmo K-vicino più vicino. Questo incarico ti richiederà di scrivere il tuo codice, oltre a utilizzare l'apprendimento psichico. Pertanto, sarebbe utile per te configurare Python questa settimana in preparazione per i compiti. Non preoccuparti; il compito è progettato per aiutarti a capire meglio l'algoritmo KNN e non sarà eccessivamente difficile poiché è il primo compito a casa. Una volta completato questo compito, approfondiremo gli aspetti concettuali dell'apprendimento automatico.

Prima di procedere oltre, diamo una rapida panoramica dello stato di avanzamento del corso. Nella prima settimana, abbiamo coperto l'introduzione all'apprendimento automatico e ai vicini più vicini. Attualmente, siamo nella seconda settimana, concentrandoci sui fondamenti computazionali. Queste basi sono cruciali poiché in seguito le utilizzeremo per implementare vari concetti di apprendimento automatico. Pertanto, è essenziale familiarizzare presto con Python e il suo utilizzo. In questa lezione parleremo principalmente di Python e di come configurarlo. Tieni presente che mostrerò il processo di installazione sul mio Mac, ma il nostro TA può aiutarti con qualsiasi domanda relativa a Windows.

Python è un linguaggio di programmazione interpretato e dinamico, che lo rende più interattivo e intuitivo rispetto ai linguaggi tipizzati staticamente come C o C++. Sebbene Python possa essere più lento di questi linguaggi, non è una preoccupazione significativa per i nostri scopi. Molte librerie di calcolo scientifico, che esploreremo nella prossima lezione, sono scritte in C o Fortran e offrono tempi di esecuzione rapidi. Python è un linguaggio di programmazione per tutti gli usi ampiamente utilizzato in varie applicazioni, inclusi framework Web come Django e servizi popolari come Instagram e Dropbox.

Confrontiamo ora Python con un linguaggio tipizzato staticamente come il C scrivendo un semplice programma. In C, dobbiamo dichiarare le variabili e specificare esplicitamente i loro tipi di dati, come numeri interi, float o caratteri. Ecco un esempio di un semplice programma in C:

#include <stdio.h>

int main() {
     int age = 25 ;
     float height = 1.75 ;
     char initial = 'J' ;

    printf( "My age is %d\n" , age);
    printf( "My height is %.2f meters\n" , height);
    printf( "My initial is %c\n" , initial);

     return 0 ;
}
In questo programma C, abbiamo dichiarato le variabili age, height e initial con i rispettivi tipi di dati. Abbiamo quindi assegnato dei valori a queste variabili e li abbiamo stampati usando printf().

Ora, confrontiamo lo stesso programma in Python:

age = 25
height = 1.75
initial = 'J'

print( "My age is" , age)
print( "My height is" , height, "meters" )
print( "My initial is" , initial)
In Python, non è necessario dichiarare esplicitamente i tipi di variabile. Puoi assegnare direttamente valori alle variabili e Python dedurrà automaticamente i tipi di dati. La funzione print() viene utilizzata per visualizzare l'output.

La semplicità e la leggibilità di Python lo rendono una scelta eccellente sia per i principianti che per i programmatori esperti. Ha un vasto ecosistema di librerie e framework che lo rendono adatto per il calcolo scientifico, l'analisi dei dati, l'apprendimento automatico e altro ancora.

Ora passiamo alla configurazione di Python sul tuo computer. Esistono diversi modi per installare Python, ma consiglio di utilizzare la distribuzione Anaconda, che viene fornita preconfezionata con molte librerie utili per il calcolo scientifico. Ecco i passaggi per installare Anaconda:

  1. Visita il sito Web di Anaconda ( https://www.anaconda.com/products/individual ) e scarica il programma di installazione appropriato per il tuo sistema operativo (Windows, macOS o Linux).

  2. Eseguire il programma di installazione e seguire le istruzioni sullo schermo. È possibile scegliere le opzioni di installazione predefinite a meno che non si disponga di preferenze specifiche.

  3. Al termine dell'installazione, dovresti avere Anaconda Navigator e Anaconda Prompt (o Anaconda PowerShell Prompt) installati sul tuo computer. Questi sono strumenti utili per la gestione di ambienti e pacchetti Python.

  4. Apri Anaconda Navigator e fai clic sulla scheda "Ambienti". Qui puoi creare un nuovo ambiente per questo corso. Fare clic sul pulsante "Crea", fornire un nome per l'ambiente (ad esempio, "apprendimento automatico") e scegliere la versione di Python (preferibilmente Python 3.x). Fare clic su "Crea" per creare l'ambiente.

  5. Una volta creato l'ambiente, fai clic sulla scheda "Home" in Anaconda Navigator. Dovresti vedere un elenco di applicazioni e ambienti disponibili. Seleziona l'ambiente appena creato dal menu a discesa nella parte superiore della finestra.

  6. Nella scheda "Home", fai clic sul pulsante "Installa" nella sezione Jupyter Notebook. Questo installerà Jupyter Notebook, che useremo per la programmazione interattiva e l'esecuzione di codice Python.

  7. Dopo l'installazione, fai clic sul pulsante "Avvia" accanto a Jupyter Notebook. Questo aprirà una nuova scheda nel tuo browser web, eseguendo Jupyter Notebook.

Congratulazioni! Hai installato correttamente Python e Jupyter Notebook utilizzando la distribuzione Anaconda. Ora sei pronto per iniziare a programmare in Python per questo corso. Nella prossima lezione, approfondiremo il calcolo scientifico con Python ed esploreremo la popolare libreria chiamata scikit-learn.

Se riscontri problemi durante il processo di installazione o hai domande, non esitare a chiedere nel forum di discussione o a contattare l'assistenza tecnica.

Tieni presente che queste istruzioni sono specifiche per Anaconda, ma se preferisci utilizzare una distribuzione Python diversa, come Miniconda o la distribuzione Python standard, puoi comunque seguire il corso.

3.1 (Optional) Python overview
3.1 (Optional) Python overview
  • 2020.09.16
  • www.youtube.com
In this optional videos, I mainly talk about the use of Python in this course. I will also show a quick demo using C (a statically typed language) vs Python....
 

3.2 (Facoltativo) Installazione di Python


3.2 (Facoltativo) Installazione di Python

Nel secondo video del corso, discuteremo il processo di configurazione e come installare Python. Nel video precedente, abbiamo trattato le basi dei linguaggi di programmazione interpretati e dinamici, evidenziando Python come linguaggio interpretato dinamico.

Prima di procedere con l'installazione, è importante guardare il video ed evitare di installare qualsiasi cosa sul computer durante la visione. Questa misura precauzionale garantisce di avere una comprensione completa delle diverse opzioni di installazione prima di prendere una decisione. L'installazione di software senza una conoscenza adeguata può portare a rimpianti in seguito.

Per iniziare, si consiglia di verificare se sul proprio computer è già installata una versione di Python aggiornata. Su Mac o Linux, puoi utilizzare il comando "which Python" per determinare il percorso e la versione dell'installazione. Allo stesso modo, su Windows, puoi utilizzare il comando "where" per trovare il percorso di installazione.

Molti Mac sono tradizionalmente dotati di una versione obsoleta di Python, in particolare Python 2. Si consiglia vivamente di aggiornare Python poiché Python 2 non è più supportato dalla comunità Python. Idealmente, si consiglia di installare Python 3.8 o 3.7, poiché la nuova versione 3.9 è ancora in fase di sviluppo.

Il metodo ufficiale per installare Python è visitare python.org e scaricare il programma di installazione. Tuttavia, un approccio alternativo spesso preferito è l'utilizzo di Anaconda o, più specificamente, Miniconda. Miniconda è una versione leggera di Anaconda che non include librerie non necessarie, risparmiando spazio di archiviazione sul tuo computer. Mentre Anaconda viene fornito con librerie preinstallate, Miniconda consente un processo di installazione più personalizzato.

Personalmente, l'istruttore consiglia di utilizzare Miniconda per la sua praticità e per l'esperienza positiva che molti membri della comunità informatica scientifica di Python hanno avuto con esso. Miniconda offre un gestore di pacchetti completo che garantisce l'installazione di tutte le versioni dei pacchetti richieste e gestisce le dipendenze dei pacchetti. Questa funzionalità semplifica il mantenimento di un ambiente di sviluppo stabile e compatibile.

Per installare Miniconda, puoi visitare il sito Web della documentazione, docs.conda.io, e passare all'ultima versione inglese della pagina di installazione di Miniconda. Da lì, puoi scegliere il programma di installazione appropriato per il tuo sistema operativo. Per gli utenti Mac, viene comunemente utilizzato il programma di installazione bash. Dopo aver scaricato il programma di installazione, eseguire lo script, accettare il contratto di licenza e scegliere il percorso di installazione.

Una volta installato Miniconda, puoi controllare la tua versione predefinita di Python aprendo una shell Python, che ora dovrebbe visualizzare la versione aggiornata. Miniconda fornisce anche strumenti per la gestione di diversi ambienti, consentendo di creare ambienti isolati per diversi progetti. Sebbene non siano necessari per questo corso, questi ambienti possono essere utili se lavori su più progetti contemporaneamente.

Per installare i pacchetti, come il pacchetto "numpy" richiesto per la lezione successiva, puoi utilizzare il gestore di pacchetti "pip" o il programma di installazione di Conda. Poiché si utilizza Miniconda, si consiglia di utilizzare il programma di installazione di Conda quando possibile, in quanto garantisce una migliore compatibilità e gestione delle versioni. Tuttavia, se un pacchetto non è disponibile in Conda, puoi ricorrere all'uso di "pip".

Nel caso in cui sia necessario installare pacchetti non disponibili in Conda, come il pacchetto "mlxtend", è possibile esplorare Conda Forge. Conda Forge è un repository guidato dalla comunità che ospita librerie supportate dalla più ampia comunità Conda. Cercando il pacchetto desiderato in Conda Forge, puoi trovare le istruzioni di installazione specifiche per quel pacchetto.

Ricorda che puoi anche aggiornare i pacchetti usando il gestore pacchetti Conda, usando comandi come "conda update" seguito dal nome del pacchetto, o con "pip" usando "pip install --upgrade" seguito dal nome del pacchetto.

Seguendo queste linee guida per l'installazione e la gestione dei pacchetti, puoi garantire una configurazione agevole ed efficiente di Python per questo corso.

Per installare i pacchetti dal canale Conda Forge, puoi utilizzare il seguente comando:

conda install -c conda-forge <nome-pacchetto>

Ad esempio, per installare il pacchetto MLX Extent da Conda Forge, dovresti usare:

conda install -c conda-forge mlx_ext

Questo comando cercherà il pacchetto nel canale Conda Forge e lo installerà nel tuo ambiente.

Se il pacchetto di cui hai bisogno non è disponibile in Conda Forge o in qualsiasi altro canale Conda, puoi anche utilizzare il gestore di pacchetti pip per installarlo. Pip è il gestore di pacchetti predefinito per Python e ti consente di installare pacchetti dal Python Package Index (PyPI).

Per installare un pacchetto usando pip, puoi usare il seguente comando:

pip install <nome-pacchetto>

Ad esempio, per installare un pacchetto chiamato "example-package" usando pip, dovresti usare:

pip installa il pacchetto di esempio

Assicurati di sostituire <package-name> con il nome effettivo del pacchetto che desideri installare.

Tieni presente che quando si utilizzano sia Conda che pip, in genere si consiglia di utilizzare Conda come gestore di pacchetti principale per mantenere la compatibilità dei pacchetti e gestire le dipendenze. Tuttavia, se un pacchetto non è disponibile in Conda, l'utilizzo di pip è un'alternativa adeguata.

Questo conclude le istruzioni di configurazione per l'installazione di Python e la gestione dei pacchetti utilizzando Conda e pip. Ricorda di guardare il video tutorial prima di installare qualsiasi cosa sul tuo computer e segui i passaggi consigliati per garantire un processo di installazione senza problemi.

3.2 (Optional) Python setup
3.2 (Optional) Python setup
  • 2020.09.16
  • www.youtube.com
In this optional video, I am demonstrating how to install Python using Miniconda on macOS. Also, I provide some brief demo of the conda package manager.-----...
 

3.3 (Facoltativo) Esecuzione del codice Python


3.3 (Facoltativo) Esecuzione del codice Python

Nel terzo e ultimo video della terza lezione, mostrerò diversi metodi per eseguire il codice Python. Questo video si concentrerà sui taccuini Jupiter, un formato di file e un programma che consente di codificare, scrivere testi, rendere equazioni e tracciare in un unico documento, che verrà utilizzato per l'imminente compito a casa.

Prima di immergerti nei taccuini di Jupiter, ti mostrerò innanzitutto il modo più semplice per eseguire il codice Python, che utilizza l'interprete Python o quello che alcune persone chiamano REPL (Read-Eval-Print Loop). L'interprete consente l'esecuzione interattiva del codice Python, il che significa che il codice viene valutato immediatamente. Per usare l'interprete, puoi aprire il tuo terminale e digitare "python". Da lì, puoi inserire espressioni Python e vedere immediatamente i risultati. Ad esempio, digitando "print(1 + 2)" verrà visualizzato il risultato "3". È inoltre possibile utilizzare l'interprete per attività più complesse, come eseguire il looping dei valori e stamparli.

Sebbene l'interprete possa essere utile per calcoli o calcoli rapidi, non è consigliato per scrivere codice più complicato. Può essere facile perdere traccia dei calcoli e diventare ingombrante scorrere indietro e trovare i comandi eseguiti in precedenza. Pertanto, per un codice più complesso, è preferibile utilizzare uno script Python o un notebook Jupiter.

Successivamente, introduco un interprete Python interattivo alternativo chiamato IPython. IPython offre caratteristiche e funzionalità aggiuntive rispetto al normale interprete, inclusa la colorazione della sintassi, la funzione cronologia per una facile modifica del codice e comandi magici. I comandi magici sono comandi speciali che iniziano con un segno di percentuale (%) e forniscono funzionalità utili. Uno di questi esempi è il comando magico "timeit", che consente di confrontare diverse implementazioni di codice. Lo dimostro implementando due funzioni per invertire le stringhe e confrontando la loro efficienza usando il comando "timeit".

Dopo aver mostrato i vantaggi di IPython, spiego che i notebook Jupiter erano originariamente chiamati notebook IPython perché erano costruiti su IPython. Anche ora, i notebook Jupiter si affidano a IPython, fornendo gli stessi vantaggi e funzionalità aggiuntive. Per installare IPython, utilizzo Conda e mostro il sito Web IPython per ulteriore documentazione.

Andando avanti, discuto il secondo metodo di esecuzione del codice Python, che utilizza gli script Python. Questo metodo prevede la creazione di un file con estensione .py, la scrittura del codice nel file e l'esecuzione dalla riga di comando. Fornisco un esempio di uno script Python che utilizza un ciclo per stampare i numeri da 0 a 4.

Infine, menziono l'importanza di aderire alle linee guida sullo stile di codifica, come PEP 8, per scrivere codice pulito e leggibile. Mostro come l'utilizzo di un linter, come Flake8, in un ambiente di sviluppo integrato come Visual Studio Code può aiutare a identificare e correggere i problemi di stile, migliorando la qualità complessiva del codice.

Il video copriva diversi modi per eseguire il codice Python, incluso l'utilizzo dell'interprete, la creazione di script Python e lo sfruttamento dei vantaggi dei notebook IPython e Jupiter. Ogni metodo ha i suoi vantaggi ed è adatto a scopi diversi.

3.3 (Optional) Running Python code
3.3 (Optional) Running Python code
  • 2020.09.16
  • www.youtube.com
In this third and last video of the optional lecture 3, I am demonstrating the different ways for running Python code: the REPL, IPython, .py scripts, and Vi...
 

4.1 Introduzione a NumPy (L04: Calcolo scientifico in Python)



4.1 Introduzione a NumPy (L04: Calcolo scientifico in Python)

In questo tutorial tratteremo le basi di NumPy, inclusa la creazione di array, l'accesso agli elementi, l'esecuzione di operazioni sugli array e altro ancora. Cominciamo!

Per iniziare, dobbiamo importare la libreria NumPy. Convenzionalmente, viene importato con l'alias np. Eseguire il codice seguente per importare NumPy:

import numpy as np
Ora che abbiamo importato NumPy, creiamo il nostro primo array. Gli array NumPy vengono creati utilizzando la funzione np.array(), che accetta un elenco Python come input. Eseguire il codice seguente per creare un array:

arr = np.array([1, 2, 3, 4, 5])
print(arr)
Dovresti vedere il seguente output:

[1 2 3 4 5]
Congratulazioni! Hai creato il tuo primo array NumPy. Ora esploriamo alcune operazioni di base che possiamo eseguire sugli array.

Accesso agli elementi dell'array

Per accedere agli elementi in un array NumPy, possiamo usare l'indicizzazione e lo slicing, in modo simile agli elenchi Python. L'indicizzazione parte da 0.

Eseguire il codice seguente per accedere agli elementi nell'array:

 print (arr[ 0 ])   # Access the first element
print (arr[ 2 ])   # Access the third element
print (arr[- 1 ])   # Access the last element
L'output sarà:

1
3
5
Possiamo anche utilizzare lo slicing per accedere a un intervallo di elementi in un array. La sintassi per lo slicing è start:stop:step, dove start è l'indice iniziale, stop è l'indice di arresto (esclusivo) e step è la dimensione del passo.

Eseguire il codice seguente per suddividere l'array:

 print (arr[ 1 : 4 ])   # Access elements from index 1 to 3
print (arr[:: 2 ])   # Access every other element

L'output sarà:

[2 3 4]
[1 3 5]
Operazioni di matrice

Gli array NumPy supportano varie operazioni matematiche, come addizione, sottrazione, moltiplicazione e divisione. Queste operazioni vengono applicate in base agli elementi agli array.

Eseguire il codice seguente per eseguire operazioni sugli array:

arr1 = np. array ([ 1 , 2 , 3 ])
arr2 = np. array ([ 4 , 5 , 6 ])

# Addition
print (arr1 + arr2)

# Subtraction
print (arr1 - arr2)

# Multiplication
print (arr1 * arr2)

# Division
print (arr1 / arr2)
L'output sarà:

 [5 7 9]
[-3 -3 -3]
[4 10 18]
[0.25 0.4  0.5]
NumPy fornisce anche varie funzioni matematiche che possono essere applicate agli array. Ad esempio, la funzione np.sin() può essere utilizzata per calcolare il seno di un array.

Eseguire il codice seguente per applicare una funzione matematica a un array:

arr = np. array ([ 0 , np.pi/ 2 , np.pi])

# Calculate sine
print (np.sin(arr))
L'output sarà:

[0.0000000e+00 1.0000000e+00 1.2246468e-16]

Forma e rimodellamento dell'array

La forma di un array NumPy rappresenta le sue dimensioni, ad esempio il numero di righe e colonne. Possiamo usare l'attributo shape per controllare la forma di un array.

Eseguire il codice seguente per verificare la forma di un array:

arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.shape)
L'output sarà:

(2, 3)
Possiamo anche cambiare la forma di un array usando la funzione reshape(). Questa funzione ci consente di ridimensionare un array senza modificarne i dati.

Eseguire il codice seguente per rimodellare un array:

arr = np.array([1, 2, 3, 4, 5, 6])
reshaped_arr = arr.reshape((2, 3))
print(reshaped_arr)
L'output sarà:

[[1 2 3]
 [4 5 6]]
Queste sono solo alcune delle operazioni di base che puoi eseguire con NumPy. La libreria offre un'ampia gamma di funzioni e capacità per lavorare con gli array in modo efficiente. Ti incoraggio a esplorare la documentazione di NumPy per saperne di più sulle sue funzionalità.
4.1 Intro to NumPy (L04: Scientific Computing in Python)
4.1 Intro to NumPy (L04: Scientific Computing in Python)
  • 2020.09.20
  • www.youtube.com
This first video in the "L04: Intro to Scientific Computing in Python" introduces NumPy on a basic level before diving into more details in the following vid...
 

4.2 Costruzione e indicizzazione di array NumPy (L04: Calcolo scientifico in Python)



4.2 Costruzione e indicizzazione di array NumPy (L04: Calcolo scientifico in Python)

Nel secondo video, vorrei discutere la costruzione e l'indicizzazione di array non Python. Le routine di costruzione di array sono blocchi o funzioni utili per la creazione di array. Sono utili quando hai bisogno di un array segnaposto che puoi successivamente popolare con valori specifici. Lasciatemi dimostrare cosa intendo.

Per creare un array riempito con il numero uno, possiamo usare la funzione quelli. Ad esempio, ones((3, 3)) genererà un array 3x3 con tutti gli elementi impostati su uno. Puoi anche specificare dimensioni diverse, come quelli((3, 4)), che creeranno una matrice 3x4 piena di uno. La funzione quelli accetta vari argomenti, incluso il parametro dtype, che determina il tipo di dati dell'array (il valore predefinito è float64 per macchine a 64 bit). Puoi impostarlo su int64 per creare un array di numeri interi. Inoltre, è possibile specificare il parametro order, che controlla il modo in cui l'array viene disposto in memoria. L'impostazione predefinita è C, che rappresenta lo stile della riga principale, ma puoi scegliere F per il layout in stile Fortran. Tuttavia, per questa classe, non devi preoccuparti di questi dettagli, poiché sono più rilevanti per combinare NumPy con il codice C o Fortran.

Allo stesso modo, la funzione zeri può essere utilizzata per creare un array pieno di zeri. Puoi usarlo allo stesso modo di quelli. Ricorda, se vuoi saperne di più su queste funzioni, puoi usare la funzione di aiuto o usare un punto interrogativo (?) in Jupyter Lab o IPython.

C'è anche la funzione empty, che crea un array vuoto senza inizializzarne i valori. Nella maggior parte dei casi, non dovrai preoccuparti dei dettagli di questa funzione, in quanto crea semplicemente un array con valori arbitrari. La funzione identità crea una matrice identità, dove gli elementi diagonali sono uno e il resto sono zeri. Può essere utilizzato per creare una matrice diagonale con valori specifici.

Passando all'indicizzazione, l'indicizzazione di base negli array NumPy è simile all'indicizzazione negli elenchi Python. È possibile accedere agli elementi utilizzando le parentesi quadre. Ad esempio, matrice[0] restituisce il primo elemento, matrice[1] restituisce il secondo elemento e così via. È anche possibile affettare, proprio come con le liste Python. Ad esempio, array[1:4] restituirà una porzione dell'array dall'indice 1 a 3 (escluso l'indice 4).

Quando si ha a che fare con array bidimensionali, è possibile utilizzare una notazione con virgola per indicizzare le due dimensioni. Il primo indice specifica la riga, mentre il secondo indice specifica la colonna. Ad esempio, matrice[0, 0] restituisce l'elemento nella prima riga e nella prima colonna, matrice[1, 2] restituisce l'elemento nella seconda riga e nella terza colonna e così via.

L'indicizzazione negativa può essere utilizzata per accedere agli elementi dalla fine di un array. Ad esempio, array[-1, -1] restituirà l'ultimo elemento dell'array. Allo stesso modo, array[-1, -2] restituirà il penultimo elemento. Questo può essere utile quando si lavora con array di grandi dimensioni, poiché non è necessario tenere traccia della lunghezza dell'array.

Per recuperare un'intera riga o colonna, è possibile omettere uno degli indici. Ad esempio, matrice[0, :] restituisce l'intera prima riga e matrice[:, 1] restituisce l'intera seconda colonna. Ciò equivale a specificare l'intervallo di indici (ad esempio, array[0, 0:3] per la prima riga). L'affettatura funziona in entrambe le dimensioni, consentendo di selezionare porzioni specifiche dell'array. Ad esempio, array[1:3, 2:4] restituisce un sottoarray costituito dalle righe 1 e 2 (esclusa la riga 3) e dalle colonne 2 e 3 (esclusa la colonna 4).

L'indicizzazione booleana è un'altra potente funzionalità di NumPy. È possibile utilizzare un array booleano per indicizzare un array, selezionando solo gli elementi che corrispondono ai valori True nell'array booleano. Ad esempio, supponiamo di avere un array chiamato array con la forma (3, 3):

array( [[1, 2, 3] ,
       [4, 5, 6] ,
       [7, 8, 9] ])

Possiamo creare un array booleano basato su una condizione, come array > 5, che restituirà il seguente array booleano:

array([[ False , False , False ],
       [ False , False , True ],
       [ True , True , True ]])
Usando questo array booleano come indice per l'array originale, possiamo selezionare solo gli elementi che corrispondono ai valori True, risultando in:

array([6, 7, 8, 9])
L'indicizzazione booleana consente una selezione flessibile ed efficiente degli elementi in base a condizioni specifiche.

Oltre all'indicizzazione di base, NumPy fornisce tecniche di indicizzazione avanzate, come l'indicizzazione di array interi e l'utilizzo di array come indici. Queste tecniche consentono operazioni di indicizzazione più complesse e non contigue sugli array. Tuttavia, sono argomenti più avanzati e potrebbero non essere necessari per la manipolazione di base dell'array.

4.2 NumPy Array Construction and Indexing (L04: Scientific Computing in Python)
4.2 NumPy Array Construction and Indexing (L04: Scientific Computing in Python)
  • 2020.09.20
  • www.youtube.com
This video explains how we can construct arrays in NumPy and how we access individual elements via indexing operations.Link to the Jupyter notebook: https://...
 

4.3 NumPy Array Math e funzioni universali (L04: Calcolo scientifico in Python)



4.3 NumPy Array Math e funzioni universali (L04: Calcolo scientifico in Python)

Dopo aver investito una considerevole quantità di tempo nella creazione di una corsa e nell'indicizzazione dei singoli valori in un array, passiamo a un argomento più intrigante: array non a pagamento, matematica e funzioni universali.

Le funzioni universali, spesso abbreviate in Ufunk o Frank, sono un concetto potente nella programmazione. Una funzione universale (Ufunk) è una forma abbreviata di una funzione universale, che consente di lavorare in modo più efficiente e conveniente con gli array Numpy. Introduce un concetto chiamato vettorializzazione.

La vettorizzazione implica l'esecuzione di un'operazione matematica o aritmetica su una sequenza di oggetti, come un array. Invece di eseguire l'operazione singolarmente su ciascun elemento dell'array, la vettorizzazione ci permette di eseguire l'operazione in parallelo, sfruttando la mancanza di dipendenze tra gli elementi.

Ad esempio, consideriamo il compito di aggiungere un numero a ogni elemento in un array. Con un ciclo Python for, iteriamo su ogni elemento e chiamiamo una funzione di addizione. Tuttavia, con la vettorizzazione, possiamo eseguire l'addizione sull'intero array contemporaneamente, senza la necessità di un ciclo. Ciò migliora notevolmente l'efficienza.

In Numpy, la vettorializzazione si ottiene utilizzando funzioni universali (Ufunk). Ci sono più di 60 Ufunk implementati in Numpy, ognuno con uno scopo specifico. Si consiglia di fare riferimento alla documentazione ufficiale per un elenco completo degli Ufunk disponibili.

Per illustrare il concetto, concentriamoci sull'addizione per elemento, un'operazione comune. Supponiamo di avere un array bidimensionale implementato come un elenco di elenchi in Python. Se vogliamo aggiungere 1 a ciascun elemento, in genere utilizzeremo cicli nidificati o comprensioni di elenchi. Tuttavia, questi approcci possono essere inefficienti, specialmente per array di grandi dimensioni.

In Numpy, possiamo usare Ufunk "np.add" per aggiungere il numero 1 all'intero array in modo vettoriale. Ciò elimina la necessità di cicli espliciti e migliora significativamente le prestazioni.

Vale la pena ricordare che Numpy sfrutta il sovraccarico dell'operatore, che consente un utilizzo intuitivo di Ufunk. Ad esempio, l'utilizzo dell'operatore "+" tra un array e un numero richiama automaticamente l'Ufunk "np.add".

Un altro Ufunk utile è "np.square", che eleva al quadrato ogni elemento in un array. Le funzioni di Ufunk possono essere unarie (operando su un singolo valore) o binarie (prendendo due argomenti). La documentazione ufficiale di Numpy fornisce maggiori dettagli sull'Ufunk disponibile.

Passando a un caso più interessante, esploriamo l'uso di Ufunk insieme al metodo "reduce". L'operazione di "riduzione" applica un'operazione lungo un asse specificato, riducendo più valori in un unico valore. Ad esempio, possiamo calcolare le somme delle colonne utilizzando "np.add" con il metodo "reduce".

In questo scenario, eseguiamo il rollover sull'asse specificato (asse 0 in questo caso) e combiniamo gli elementi utilizzando l'operazione specificata. L'operazione "reduce" è comunemente associata a concetti come "map reduce" e Hadoop, in cui i calcoli vengono distribuiti su più nodi e quindi combinati per produrre il risultato finale.

Anche se questo può sembrare opprimente, la comprensione di questi concetti consente una programmazione più efficiente ed efficace con Numpy. Sfruttando Ufunk e la vettorizzazione, possiamo eseguire operazioni complesse sugli array con facilità e ottimizzare il nostro codice per migliorare le prestazioni.

Ricorda di fare riferimento alla documentazione ufficiale di Numpy per un elenco completo di Ufunk disponibili, nonché esempi e linee guida per l'utilizzo. Esplorare le possibilità di Ufunk amplierà il tuo toolkit e ti aiuterà ad affrontare varie attività computazionali in progetti futuri.

Quindi, in NumPy, abbiamo una funzione chiamata reduce, che ci permette di eseguire operazioni di riduzione lungo un asse specificato di un array. L'operazione di riduzione combina più valori in un unico valore. Per impostazione predefinita, la riduzione viene applicata lungo il primo asse (asse 0) dell'array.

Facciamo un esempio per capire meglio questo concetto. Considera il seguente array:

array( [[1, 2, 3] ,
       [4, 5, 6] ,
       [7, 8, 9] ])
Se vogliamo calcolare le somme delle colonne, possiamo usare la funzione reduce. Questa operazione eseguirà il rollover del primo asse (asse 0) e combinerà i valori in ogni colonna. Quindi, il risultato sarà un array unidimensionale contenente le somme di ciascuna colonna.

Per ottenere ciò, possiamo usare la funzione np.add, che esegue l'addizione per elemento. Passiamo np.add come argomento della funzione da ridurre, indicando che vogliamo sommare i valori lungo l'asse specificato.

Ecco come appare il codice:

import numpy as np

array = np. array ([[ 1 , 2 , 3 ],
                  [ 4 , 5 , 6 ],
                  [ 7 , 8 , 9 ]])

column_sums = np.reduce(np.add, array )
print (column_sums)
L'output sarà:

[12 15 18]
In questo esempio, la funzione reduce esegue un'iterazione sulle colonne dell'array e somma i valori. Combina la prima colonna (1 + 4 + 7), la seconda colonna (2 + 5 + 8) e la terza colonna (3 + 6 + 9) in un unico array che rappresenta le somme delle colonne.

Questo approccio è più efficiente dell'iterazione manuale sulle colonne e dell'aggiunta dei valori uno per uno. L'operazione vettorizzata fornita da NumPy ci consente di eseguire il calcolo in parallelo, sfruttando gli algoritmi sottostanti ottimizzati.

Tieni presente che reduce può essere utilizzato con varie altre funzioni oltre a np.add, a seconda dell'operazione che desideri eseguire. Il concetto di riduzione è potente e può essere applicato a molti scenari diversi.

4.3 NumPy Array Math and Universal Functions (L04: Scientific Computing in Python)
4.3 NumPy Array Math and Universal Functions (L04: Scientific Computing in Python)
  • 2020.09.20
  • www.youtube.com
This video discusses one of the core aspects of NumPy: it's functions that allow us to work with NumPy arrays efficiently.Jupyter notebook: https://github.co...
 

4.4 NumPy Broadcasting (L04: Calcolo scientifico in Python)



4.4 NumPy Broadcasting (L04: Calcolo scientifico in Python)

NumPy offre un'affascinante funzionalità nota come "broadcasting", che introduce dimensioni implicite e ci consente di eseguire operazioni che sarebbero tipicamente impossibili entro i confini della rigida algebra lineare. Questo concetto di trasmissione consente una maggiore flessibilità e praticità quando si lavora con gli array.

Sfruttando la trasmissione, NumPy può allineare automaticamente array con forme diverse, essenzialmente espandendoli per abbinarli ed eseguire operazioni a livello di elementi. Questa creazione di dimensioni implicite ci consente di eseguire senza problemi operazioni su array di dimensioni variabili, ottenendo un codice conciso ed efficiente.

Nel contesto dell'algebra lineare, dove la stretta aderenza alle regole matematiche governa le operazioni, la trasmissione fornisce un potente strumento per semplificare calcoli complessi. Ci consente di eseguire calcoli su matrici con forme disparate, eliminando la necessità di rimodellamento manuale o looping degli elementi.

Grazie al broadcasting, possiamo applicare senza sforzo operazioni su array con dimensioni implicite, ottenendo risultati che altrimenti richiederebbero un'estesa manipolazione manuale. Questa capacità amplia la portata di ciò che possiamo realizzare con NumPy, rendendolo una libreria versatile e indispensabile per il calcolo scientifico e l'analisi dei dati.

4.4 NumPy Broadcasting (L04: Scientific Computing in Python)
4.4 NumPy Broadcasting (L04: Scientific Computing in Python)
  • 2020.09.20
  • www.youtube.com
One of the cool things about NumPy is that it allows us to "broadcast." Here, that means that it is creating implicit dimensions that allow us to do things t...
 

4.5 Indicizzazione avanzata NumPy -- Visualizzazioni e copie della memoria (L04: Calcolo scientifico in Python)



4.5 Indicizzazione avanzata NumPy -- Visualizzazioni e copie della memoria (L04: Calcolo scientifico in Python)

In questo quinto video, approfondiremo ancora una volta il tema dell'indicizzazione. Tuttavia, a differenza del video iniziale in cui abbiamo trattato l'indicizzazione di base, ora esploreremo l'indicizzazione avanzata. Questo segmento introdurrà concetti come le visualizzazioni di memoria e la creazione di copie di memoria, che sono pratiche cruciali per evitare errori non intenzionali, come la sovrascrittura errata dei valori dell'array. Capire questo è fondamentale in quanto ci aiuta a prevenire bug e comportamenti imprevisti in NumPy.

Ora, cominciamo. Nella sezione precedente, abbiamo discusso un aspetto degli array NumPy chiamato "viste". Le visualizzazioni vengono create quando utilizziamo l'indicizzazione regolare o le operazioni di suddivisione di base. Questi punti di vista agiscono come dimensioni implicite, consentendoci di eseguire operazioni che non sono fattibili all'interno del rigido quadro matematico dell'algebra lineare. Tuttavia, lavorare con le viste può essere rischioso poiché potremmo modificare accidentalmente l'array originale senza rendercene conto.

Per illustrare questo, consideriamo un semplice esempio. Supponiamo di avere un array bidimensionale con due righe e tre colonne. Per comodità, assegnerò la prima riga a una variabile separata chiamata "first_row". Ora, ecco il punto cruciale: assegnare la prima riga a una variabile crea una vista, non un nuovo oggetto. Significa che questa variabile punta semplicemente alla posizione dell'array originale in memoria. Di conseguenza, se modifichiamo i valori in questa variabile, modificheremo anche i valori corrispondenti nell'array originale.

Per dimostrarlo, incrementiamo ogni elemento nella variabile "first_row" di 99. L'esecuzione di questa operazione non solo cambierà i valori nella variabile ma sovrascriverà anche i valori nella prima riga dell'array originale. Questo comportamento serve come suggerimento che stiamo lavorando con una vista piuttosto che con un oggetto indipendente. Non esserne consapevoli può essere pericoloso, poiché è facile sovrascrivere involontariamente i valori nell'array originale mentre si lavora con una vista.

D'altra parte, le viste possono essere incredibilmente utili per l'efficienza della memoria poiché ci consentono di evitare copie di array non necessarie. Tuttavia, ci sono situazioni in cui potremmo voler creare esplicitamente una copia di un array. A tale scopo possiamo utilizzare la funzione "copia", che genera un nuovo array con gli stessi valori dell'originale. Nell'esempio fornito, creo una copia della seconda riga dell'array utilizzando la funzione "copia". In questo modo, qualsiasi modifica apportata alla variabile "first_row" non influirà sull'array originale.

È importante notare che mentre lo slicing e l'indicizzazione basata su numeri interi creano viste di memoria, esiste un altro tipo di indicizzazione chiamato "indicizzazione di fantasia" che produce copie dell'array. L'indicizzazione fantasia si riferisce all'utilizzo di più indici interi per selezionare elementi specifici da un array. Questa funzionalità è chiamata "fantasia" perché non è supportata nelle normali liste Python. Tuttavia, NumPy ci consente di eseguire questo tipo di indicizzazione, che può essere piuttosto potente.

Ad esempio, in un normale elenco Python, non possiamo recuperare contemporaneamente il primo e il terzo elemento. Tuttavia, in NumPy, possiamo ottenere questo risultato utilizzando un'indicizzazione di fantasia. Allo stesso modo, possiamo usare l'indicizzazione di fantasia per selezionare colonne specifiche da un array bidimensionale. Vale la pena notare che l'indicizzazione di fantasia risulta sempre in una copia dell'array, non in una vista.

La distinzione tra visualizzazioni e copie è correlata alle considerazioni sull'efficienza in NumPy. Lo slicing ci consente di memorizzare nella cache determinati valori, ottimizzando le prestazioni. Tuttavia, l'implementazione di questo meccanismo di memorizzazione nella cache con un'indicizzazione fantasiosa non è semplice poiché non è possibile estrarre un blocco contiguo di memoria. Invece, selezioniamo singoli valori, portando alla creazione di un nuovo array. Questo comportamento spiega perché l'indicizzazione elaborata produce copie anziché visualizzazioni.

Un altro aspetto interessante dell'indicizzazione di fantasia è che ci consente di riorganizzare l'ordine delle colonne in un array. Specificando gli indici di colonna desiderati utilizzando l'indicizzazione di fantasia, possiamo mescolare le colonne secondo necessità.

Le maschere booleane in NumPy sono un modo efficiente e potente per filtrare gli array in base a determinate condizioni. Una maschera booleana è semplicemente un array NumPy di valori booleani (True o False) che ha la stessa forma dell'array originale. Applicando la maschera booleana all'array originale, possiamo selezionare gli elementi che soddisfano la condizione data e scartare il resto.

Per creare una maschera booleana, definiamo prima una condizione che restituisca un valore booleano per ogni elemento dell'array. Ad esempio, supponiamo di avere un array chiamato arr:

import numpy as np
arr = np.array([1, 2, 3, 4, 5])
Possiamo creare una maschera booleana basata su una condizione, come selezionare solo gli elementi maggiori di 3:
mask = arr > 3
La maschera booleana risultante, mask, sarà [False, False, False, True, True]. Ogni elemento nella maschera corrisponde alla stessa posizione nell'array originale, indicando se la condizione è vera o falsa per quell'elemento.

Per applicare la maschera booleana e recuperare gli elementi che soddisfano la condizione, possiamo semplicemente utilizzare la maschera come indice per l'array:

filtered_arr = arr[mask]
Il risultante filtered_arr sarà [4, 5], che contiene solo gli elementi maggiori di 3 dall'array originale.

Le maschere booleane possono essere combinate utilizzando operatori logici come & (e), | (o) e ~ (non) per creare condizioni più complesse. Per esempio:

mask = (arr > 2) & (arr < 5)
filtered_arr = arr[mask]
Questa condizione seleziona elementi maggiori di 2 e minori di 5, con il risultato che filtered_arr è [3, 4].

Le maschere booleane sono particolarmente utili quando si lavora con set di dati di grandi dimensioni o si eseguono filtraggio e analisi dei dati. Consentono operazioni efficienti e concise sugli array senza la necessità di cicli espliciti o controlli delle condizioni.

Oltre a filtrare gli array, le maschere booleane possono essere utilizzate anche per l'assegnazione degli elementi. Assegnando nuovi valori agli elementi selezionati tramite la maschera booleana, possiamo modificare parti specifiche dell'array in base a una condizione.

Nel complesso, le maschere booleane forniscono un modo flessibile ed efficiente per manipolare e filtrare gli array NumPy in base a condizioni specificate, rendendole uno strumento prezioso per l'elaborazione e l'analisi dei dati.

4.5 NumPy Advanced Indexing -- Memory Views and Copies (L04: Scientific Computing in Python)
4.5 NumPy Advanced Indexing -- Memory Views and Copies (L04: Scientific Computing in Python)
  • 2020.09.20
  • www.youtube.com
We previously covered basic indexing. NumPy allows us to perform more advanced indexing beyond what regular Python lists are capable of. Jupyter notebook: ht...
Motivazione: