Grazie Beppe per la risposta, temo che il nostro disaccordo rimanga perché è su un livello direi "filosofico" o "ermeneutico".

L'interpretazione di una "rappresentazione" (cioè di una sequenza di bit) come "dato" (elemento passivo) o "istruzione" (elemento attivo) non è intrinseca ma è strettamente dipendente dall'automa a cui la facciamo manipolare. In astratto qualunque sequenza di bit può essere interpretata in un modo o nell'altro.

È la stessa osservazione che ha fatto anche Giacomo nel suo ultimo messaggio di risposta a te.

A seconda di come uno definisce l'automa alcune rappresentazioni diventano "istruzioni" e sono quindi eseguibili altre no, ma non esiste una distinzione intrinseca, "a priori".

Il mio intervento aveva lo scopo di mettere in luce questa dualità delle "rappresentazioni".

Ho parlato della Macchina Universale di Turing (MUT) perché in essa questa dualità è chiaramente evidente. Questo unico automa, quello appunto definito dalla matrice di transizione della MUT (l'interprete, usando la tua terminologia), permette di replicare qualunque altra Macchina di Turing semplicemente sfruttando la natura duale delle rappresentazioni. In questo senso le uniche vere "istruzioni" sono quelle della matrice di transizione della MUT, che sono del tutto generiche. Ciò che fa la differenza è quale "rappresentazione" la MUT elabori.

Analogamente, in un automa X realizzato con l'architettura di von Neumann, l'interprete equivalente alla matrice di transizione della MUT è realizzato con un semplice automa a stati finiti che esegue ad libitum il ciclo decodifica-esecuzione-caricamento. Le uniche vere "istruzioni a priori" sono quindi quelle di questo automa a stati finiti. Ciò che accade quando una "rappresentazione" viene decodificata dipende da come è stato definito l'automa X, ovvero da come è stato definito il "set di istruzioni" che l'automa X deve essere in grado di eseguire.

In altre parole, una "rappresentazione" è un dato o un'istruzione solo "a posteriori", avendo definito qual è l'automa di riferimento da considerare.

Ciao, Enrico


Il 11/09/2024 18:38, Giuseppe Attardi ha scritto:
Mi spiace dover dissentire da Enrico.
La Macchina di Turing dispone di istruzioni completamente distinte dai dati, si tratta degli stati e della matrice di transizione tra essi, e che nulla hanno a che vedere con i dati letti/scritti sul nastro della sua working memory.

Quando si introduce la Macchina di Turing Universale TMU  si effettua un’operazione di codifica della macchina M in una rappresentazione alpha che viene fornita in input alla TMU, insieme ai dati di input per la stessa, in modo che TMU(alpha, x) = M((x).

La macchina TMU svolge il compito di interpreter del codice della macchina M. La macchina M stessa è un interprete del suo linguaggio macchina.
Nelle macchine moderne microprogrammate, la CPU è l’interprete del linguaggio macchina, che è a sua volta implementato come interprete del linguaggio di microcodice.
La struttura a livelli si ripete, con linguaggi come l’assembler, intepretati da un interprete di assembler o tradotti in linguaggio macchina da un assembler. Per i linguaggi a più alto livello, si usano sia interpreti del linguaggio ad alto livello, oppure compilatori in linguaggio macchina o una soluzione intermedia, ossia compilazione su macchina virtuale (es. JVM) che viene a sua volta interpretata. Poi vi sono ulteriori livelli, implementati attraverso librerie o una combinazione di librerie e hardware, come nel caso delle GPU.
Quindi nei sistemi moderni esistono diversi livelli di macchine, ognuno col suo proprio linguaggio macchina, in quello che David Patterson chiama the wheel of reincarnation.
Il fatto che le istruzioni di un livello possano essere rappresentate come dati per il livello superiore non ne cambia la natura.
In alcuni linguaggi la rappresentazione è possibile nello stesso livello: ad esempio in Lisp i programmi sono espressi come S-espressioni e questo consente di scrivere in Lisp dei macro-processori per estendere il linguaggio. In Java il meccanismo della Reflection consente di manipolare i metodi di una classe e analogamente in Python.

In altri termini i programmi possono essere codificati come dati e questo consente di fare su di essi tante operazioni utili: interpretazione, compilazione, trasformazioni, ottimizzazioni, linking, ecc. Ma ciò non ne cambia la natura di istruzioni, perché solo se rispettano il formato dell’interprete a cui vanno forniti possono essere eseguiti.
Provate a caricare un eseguibile 386 su un ARM, o anche solo un COFF su un ELF (formati binari diversi per 386).

In altri termini, qualunque istruzione può essere rappresentata come dato, ma non ogni dato può essere interpretato come istruzione. Ossia la semantica di un’istruzione è strettamente legata al suo interprete, quella di un dato no.

On 10 Sep 2024, at 17:25, nexa-request@server-nexa.polito.it wrote:

From: Enrico Nardelli <nardelli@mat.uniroma2.it>
To: nexa@server-nexa.polito.it
Subject: Re: [nexa] "pogrammazione statistica" o "intelligenza
  artificiale"? [era: AI Training is Copyright Infringement]
Message-ID: <b6ea2a4e-5645-4f80-8949-e684f34e66a5@mat.uniroma2.it>
Content-Type: text/plain; charset="utf-8"; Format="flowed"

Scusate, intervento nell'interessante discussione in corso tra Giacomo e
Beppe per fare chiarezza in termini semplici, per chi magari sa meno di
informatica, su come funziona un'architettura di von Neumann (detta
anche di Turing - von Neumann per motivi che saranno chiari nel seguito).

L'architettura di von Neumann viene anche detta "a programma
memorizzato" perché il programma viene scritto (cioè caricato) nella
memoria. Nella realizzazione più semplice possibile di tale
architettura, il programma viene scritto in memoria a partire un
indirizzo prefissato e l'hardware su cui viene mandato in esecuzione il
programma viene realizzato in modo tale che all'accensione venga portata
nella CPU per l'esecuzione esattamente l'istruzione a tale indirizzo
prefissato.

Essa viene decodificata ed eseguita e poi si carica la nuova istruzione,
che per default è quella all'indirizzo successivo di memoria, e si
riesegue il ciclo decodifica - esecuzione - caricamento. Questo processo
si ripete per eseguire in sequenza tutte le istruzioni del programma, a
meno che l'istruzione appena eseguita non sia un'istruzione di salto,
che ha l'effetto di far sì che la nuova istruzione da eseguire sia
invece quella a un altro indirizzo. Con questo meccanismo basta riuscire
a portare nella CPU un'istruzione diversa da quelle che il programmatore
originale ha predisposto per far deviare completamente il corso
dell'esecuzione e iniziare a eseguire come "istruzioni" ciò che c'è in
celle di memoria che in teoria dovrebbero avere solo "dati".

Quindi, non c'è vera distinzione da programma e dati nell'informatica.

Questo natura intrinsecamente duale delle "rappresentazioni" (termine
che uso per fondere la valenza di "dato" e di "istruzione") era stata
messa in luce anche da Alan Turing quando descrisse la MUT (Macchina
Universale di Turing). Essa è un caposaldo culturale dell'informatica,
analogo alla doppia valenza del DNA in biologia, come elenco delle
istruzioni per un organismo in sviluppo e contemporaneamente come dati
per tali istruzioni.

(piccolo spazio pubblicità - INIZIO)

A quelli che ne vogliono sapere di più sull'architettura di von Neumann
suggerisco il paragrafo 4.2.2 del mio libro
https://themiscrime.com/it/edizioni-themis/digitale-societa/item/547-la-rivoluzione-informatica
in cui faccio vedere attraverso un semplice esempio a passo a passo come
una macchina a registri (una possibile implementazione dell'architettura
di von Neumann) esegue un piccolo programma. L'intera sezione 4.2
(Automa e linguaggio) discute come si realizza, concettualmente, una
"macchina" che calcola.

A quelli che vogliono sapere di più sulla natura duale delle
rappresentazioni suggerisco la sezione 4.6 sempre del mio libro
https://themiscrime.com/it/edizioni-themis/digitale-societa/item/547-la-rivoluzione-informatica
.

(piccolo spazio pubblicità - FINE)

Ciao, Enrico

Il 10/09/2024 15:31, Giacomo Tesio ha scritto:
On Tue, 10 Sep 2024 10:13:10 +0200 Giuseppe Attardi wrote:
Si può riassumere dicendo che...
Sì, ma non stiamo solo chiacchierando fra noi e questo scambio sul
crinale fra informazione e dato, fra matematica e informatica, può
essere di interesse per molti iscritti alla lista Nexa, se riusciamo
a mantenerlo intellegibile anche ai non programmatori.
Il codice che calcola f fa uso di theta, ma non è theta che esegue
alcun calcolo e non può essere chiamato software.
[...]
L’architettura Von Neuman distingue tra istruzioni e dati: le prime
sono caricate nella CPU, i secondi nella ALU.
Anzitutto io ho parlato di macchine programmabili, non specificatamente
dell'architettura von Neumann che rappresenta solo **una**
delle architetture possibili per tali macchine.
Inoltre anche nell'architettura von Neumann nessuna istruzione "esegue
alcun calcolo": è l'unità di calcolo all'interno della CPU ad
azionare la circuiteria associata a ciascuna istruzione.
Le Vector Reducing Machines costituiscono una classe di architetture
diverse (ciascuna caratterizzata dalla rispettiva topologia), ma
ciascuna esegue programmi codificati come matrici di dimensionalità
appropriata che rappresentano funzioni fra spazi vettoriali distinti.
ma rimangono istruzioni, se caricate nella CPU.
In realtà no: quando vengono caricate nelle CPU moderne, le istruzioni
definite nella ISA vengono trasformate in microcodice proprietario
(come 380° ricorda spesso): dunque sono trattate come dato
_ANCHE_ dalla CPU.
Quindi, se theta "non può essere chiamato software", non possono essere
chiamati software nemmeno Windows, Linux o Android.
Semmai le istruzioni, che sono conservate in memoria, possono essere
trattate come dati, in programmi che si automodificano
Mica solo in programmi che si automodificano!
Ogni compilatore, ogni interprete e ogni macchina virtuale tratta le
istruzioni come dati. Ogni sistema operativo le tratta come dati mentre
le salva sul filesystem o le carica in RAM ad ogni page fault.
Per non parlare dei molti compilatori JIT (just in time) che caricano in
memoria le istruzioni di un eseguibile RISC-V, le traducono al volo
in istruzioni x86 e per poi farle eseguire alla CPU, trattando sia le
istruzioni RISC-V che quelle x86 come dati. [1]
Gli esempi sono innumerevoli senza nemmeno nominare LiSP!
(ops! :-D)
Perché?
Perché gli eseguibili _sono_ dati. Come lo è il codice sorgente.
Sono rappresentazioni trasferibili di informazioni.
Infatti, come ho provato a spiegare nella mail precedente, per ogni
sequenza di byte (foto, film, audio, testo, /dev/random etc...) puoi
costruire infinite macchine programmabili che eseguono quella
sequenza di byte per determinare il proprio comportamento.
Ne consegue che qualsiasi dato è eseguibile esattamente come qualsiasi
eseguibile è dato. [2]
Ma c'è di più: poiché puoi sempre scrivere un compilatore che trasformi
qualunque sequenza di byte in una diversa sequenza eseguibile per una
qualche macchina programmabile, ogni dato è anche codice sorgente.
Ne consegue che l'insieme dei dati, l'insieme degli eseguibili e
l'insieme dei codici sorgente coincidono. [3]
Q.E.D. :-D
La distinzione è puramente colloquiale, legata all'uso che stiamo
facendo della sequenza di byte in un certo momento, ma è indipendente
da qualsiasi caratteristica intrinseca della sequenza di byte.
una rete neurale calcola una funzione f(theta, x) = y
Proviamo a sostituire i termini antropomorfici:
"una Vector Reducing Machine implementa una funzione f(theta, x) = y"
Se invece di una "rete neurale" che "calcola" mettiamo una macchina
che implementa, la frase è meno evocativa ma descrive più precisamente
ciò che effettivamente accade.
La funzione f infatti appartiene all'insieme delle informazioni nelle
nostre menti, esperienze soggettive di pensiero comunicabile, ma
fintanto che rimane lì dentro, non può avere effetti sul mondo esterno.
Se vogliamo che abbia effetti dobbiamo esprimerla, imprimendola sui
componenti di una macchina che la implementa. Questa macchina può
essere fisica o virtuale: il già citato llama.cpp è un esempio di
macchina virtuale che implementa la funzione f.
theta sono i parametri del modello
Utilizzare il termine "modello" è errato e fuorviante perché richiama
un modello statistico che per definizione fornisce informazioni
intellegibili sul campione statistico da cui viene calcolato.
Matematicamente, theta è la prima variabile indipendente di f.
Ma dal punto di vista informatico, theta è l'eseguibile che determina
in modo preciso e deterministico il comportamento della Vector Reducing
Machine che implementa f.
Ossia non bastano i dati (theta) per modificare f.
Stai confondendo la funzione f : t -> x -> y, con la funzione
g : x -> y ottenuta attraverso l'applicazione parziale di un
particolare theta a f.
Chiudere f su un theta' diverso è sufficiente ad ottenere una
funzione g' diversa, senza alterare in alcun modo f.
Questo perché f descrive una macchina programmabile e theta uno dei
possibili programmi che tale macchina può eseguire.
Infatti, come tu stesso osservi,
Theta è del tutto inutile senza f.
esattamente come un binario x86 (o ARM o RISC-V etc...) è del tutto
inutile senza una macchina che lo esegua.
____
Passiamo ora alle minuzie da nerd:
- ne si codifica gli elementi come vettori numerici attraverso
 una analisi statistica
Nel caso dei testi si fa una tokenizzazione (ad esempio con le regole
di Porter)
Porter descrive il suo algoritmo come:
"""
a process for removing the commoner morphological and inflexional
endings from words in English. Its main use is as part of a term
normalisation process...
""" https://tartarus.org/martin/PorterStemmer/ Nota le parole "commoner" e "normalization": si tratta di (e si basa su)
una analisi _statistica_ del testo.
Nessuno di questi lo chiamerei un’analisi statistica.
Nel caso della compilazione della matrice degli embedding (l'eseguibile
della VRM) a partire dai testi sorgente, sono d'accordo.
Non è una _analisi_ statistica ma un processo di _compilazione_
statistica (parte di un più ampio processo di _programmazione_
statistica che parte dalla ricerca e selezione dei testi sorgente).
Tale processo NON produce infatti un _modello_ statistico delle
relazioni presenti nel dataset utilizzato, ma un eseguibile per
una specifica Vector Reducing Machine.
Si tratta di un processo statistico di compilazione perché, sia ad ogni
batch che complessivamente, le variazioni applicate all'eseguibile
dipendono esclusivamente dalla frequenza delle coppie di vettori
input + next token presenti nel data set.
Al termine del processo, la matrice risultante è contemporaneamente
- un eseguibile per tutte le Vector Reducing Machines con quella
 topologia
- una compressione lossy di TUTTI i testi utilizzati durante il
 processo di compilazione (come dimostra l'utilizzo di filtri
 anti plagio sull'output prodotto dal LLM per nascondere le
 prove del plagio avvenuto il processo di compilazione.
Nota poi come smettere di usare una terminologia antropomorfa e
riconoscere la compilazione dell'eseguibile per una VRM come
parte di un processo di programmazione statistica, fa venir
meno alcune distinzioni utili soltanto a deresponsabilizzare
chi realizza questi software come quella fra supervised e
unsupervised "training".
Nessuna AI fa "training" unsupervised, semplicemente esistono
metodologie diverse di programmazione statistica applicabili
a contesti diversi, in alcuni dei quali è possibile valutare
automaticamente l'errore contenuto nell'output prodotto dalla
VRM (ricorderai ad esempio AlphaGo).
A presto!
Giacomo
[1] i primi che mi vengono in mente:
   https://michaeljclark.github.io/
   https://github.com/libriscv/libriscv
[2] se preferisci una dimostrazione equivalente ma dotata di pedigree
  accademico, la trovi a pagina 23 di questo manuale:
  https://theory.cs.princeton.edu/complexity/book.pdf
[3] naturalmente non tutte le macchine programmabili sono in grado di
   eseguire qualsiasi sequenza di byte: per ottenere eseguibili
   supportati da una specifica macchina programmabile che insista
   su un sottoinsieme di tale universo, scriviamo compilatori che
   rappresentano funzioni da un sottoinsieme di nostra scelta (i cui
   elementi chiamiamo "sorgenti") e l'insieme contenente gli eseguibili
   di quella macchina (e i possibili messaggi di errore :-D).
--

-- EN

https://www.hoepli.it/libro/la-rivoluzione-informatica/9788896069516.html
  ======================================================
Prof. Enrico Nardelli
Past President di "Informatics Europe"
Direttore del Laboratorio Nazionale "Informatica e Scuola" del CINI
Dipartimento di Matematica - Università di Roma "Tor Vergata"
Via della Ricerca Scientifica snc - 00133 Roma
home page: https://www.mat.uniroma2.it/~nardelli
blog: https://link-and-think.blogspot.it/
tel: +39 06 7259.4204 fax: +39 06 7259.4699
mobile: +39 335 590.2331 e-mail: nardelli@mat.uniroma2.it
online meeting: https://blue.meet.garr.it/b/enr-y7f-t0q-ont
--

-- EN

https://www.hoepli.it/libro/la-rivoluzione-informatica/9788896069516.html
======================================================
Prof. Enrico Nardelli
Past President di "Informatics Europe"
Direttore del Laboratorio Nazionale "Informatica e Scuola" del CINI
Dipartimento di Matematica - Università di Roma "Tor Vergata"
Via della Ricerca Scientifica snc - 00133 Roma
home page: https://www.mat.uniroma2.it/~nardelli
blog: https://link-and-think.blogspot.it/
tel: +39 06 7259.4204 fax: +39 06 7259.4699
mobile: +39 335 590.2331 e-mail: nardelli@mat.uniroma2.it
online meeting: https://blue.meet.garr.it/b/enr-y7f-t0q-ont
======================================================

--