TensorFlow Lite for Commodore 64s

Cette catégorie traite de développements récents destinés à nos vieilles machines, applications, jeux ou démos... Amis programmeurs, c'est ici que vous pourrez enfin devenir célèbres!

Modérateurs : Papy.G, fneck, Carl

Avatar de l’utilisateur
ZamZam
Messages : 195
Inscription : 09 nov. 2020 16:10
Localisation : TOUL (54200) Meurthe & Moselle

Re: TensorFlow Lite for Commodore 64s

Message par ZamZam »

Intéressant
Coté programmation, comme il fournit le parser, cela permettrait de l'adapter à d'autres Basic et comme il l'indique de générer du code assembleur pour une plus grande rapidité.
Quel serait le champ d'application de cette technologie sur ces anciens ordinateurs, au-delà de l'exploit technique ?
Jean-Luc
fzalfa
Messages : 244
Inscription : 04 août 2008 15:18
Localisation : Le Pontet
Contact :

Re: TensorFlow Lite for Commodore 64s

Message par fzalfa »

il va falloir composer une la faible puissance de calcul de la machine...

LAurent
SGI sinon rien !!!
gotcha
Messages : 2759
Inscription : 30 mars 2017 11:39
Localisation : Isère
Contact :

Re: TensorFlow Lite for Commodore 64s

Message par gotcha »

Les réseaux neuronaux utilisent à la base des nombres flottants, mais peuvent être dans beaucoup de cas 'quantifiés' en entier 8 bit (mais aussi 4 bits, 16 bits, ou autre). Cela donne généralement une bonne approximation en demandant beaucoup moins de puissance de calcul et aussi en prenant moins de place en mémoire. TensorFlow Light permet d'exprimer ces réseau 'quantifiés' 8 bits de manière efficace.

Alors, si l'état de l'art d’aujourd’hui utilise encore du 8 bits (Le TPU de Google par exemple fait des calculs sur 8 bits), ça a dû faire tilt dans la tête de certains, d'où cette expérimentation :D

L'exemple donné est très très simple: un réseau avec 3 'neurones' qui prends un flottant en entrée et génère un flottant mais qui fait des calculs avec des entiers. Ça serait intéressant de prendre des réseaux un peu plus gros, tout en restant petits, par exemple une reconnaissance de caractère 8x8.
Amstrad CPC et Goupil power :mrgreen:
Bénévole à l'association pour un conservatoire de l’informatique et de la télématique (https://www.aconit.org)
Fool-DupleX
Messages : 2286
Inscription : 06 avr. 2009 12:07

Re: TensorFlow Lite for Commodore 64s

Message par Fool-DupleX »

Je ne doute pas que le gars est un expert de son domaine, mais je suis toujours perplexe face à cette propension à vouloir réinventer la roue, en moins rond.

http://fr.1001mags.com/parution/svm/num ... e-integral

Je cite : "Quand on aura bien compris le fonctionnement de NEURO.BAS, on pourra l'utiliser à d'autres fins en changeant la nature des symboles. Pour faire de la reconnaissance de caractères, les symboles deviennent les coordonnées des points d'une matrice de caractères et les lettres de l'alphabet."

Publié dans Science&Vie Micro no. 69 de février 1989, ce programme en BASIC entraine le modèle (ce que ne fait évidemment pas Tensorflow Lite) et répond ensuite aux requêtes avec le moteur d'inférence ainsi généré. Certes, l'entrainement prend des heures, compte tenu de la puissance de calcul de l'époque (et du fait que c'est en BASIC !), mais le moteur d'inférence, lui, est instantané (au lieu de plusieurs secondes) et en plus, générique pour le type de problème considéré (on propage les entrées et on regarde la sortie). Alors que dans l'exemple qui nous occupe, on produit des règles de résolution complètement figées, à l'extérieur du système, et ni plus ni moins qu'une formule très très compliquée et pas optimisée du tout pour calculer le sinus.

J'ouvre donc le débat, était-ce mieux avant ?
__sam__
Messages : 7924
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: TensorFlow Lite for Commodore 64s

Message par __sam__ »

Je l’ai codé cet algorithme de SVM 1989 à l’époque. C’était le tout début des réseaux neuronaux. Peu après durant mon DEA il y avait cette matière au programme. A l’époque (début des années 90) les reseaux n’avaient que 2 couches, et l’état de l’art développé au service d’etudes de la poste et des telecom (s.e.p.t de Caen) était de pouvoir lire les codes postaux et les chèques manuscripts en numérisant les chiffres et lettres en 16x16 ou a peu près. On a longtemps pensé pouvoir faire mieux, mais dans les faits les réseaux de neurones n’ont pas trop évolués et autour de l’an 2000, ils étaient plus ou moins abandonnés.

Mais, ils sont là de nos jours. Que s’est il passé? Le deep learning !

Avec la montée en puissance des machines, et surtout l’apparition de corpus d’apprentissage gigantesques, certains qui n’avaient pas totalement abandonnés les reseaux neuronaux (dont Yann Le Cun qui vient de recevoir le prix Turing pour cela) ont essayé des apprentissages sur des reseaux avec beaucoup, mais vraiment beaucoup de couches et des fonctions de seuilages différentes de ce qu’on faisait 10 ans plus tôt permettant une retroaction, un apprentissage, pour des réseaux très très profonds. Miraculeusement (car personne n’y croyait plus trop dans ces neurones artificiels), ils ont obtenus des résultats. Il n’a alors pas fallu longtemps pour que le secteur privé, Facebook en l’occurence, l’emploient lui et sa technique pour la reconnaissance automatique des images publiées (que voilà un corpus d’apprentissage idéal que tous ces posts facebook).

L’apprentissage supervisé des réseaux profonds marche tellement bien, que maintenant cette technique est disponible gracieusement pour tous sur les serveurs cloud AWS et se construisent à base de code python et de tensorflow. C’est vraiment très simple (faites le tuto tensorflow de aws pour voir). Attention, ça n’est pas python qui fait vivre le réseau profond, mais une tetrachié de GPU dispersés dans le cloud. Python est juste là pour décrire le réseau, lui fournir l’entrée, récupérer la sortie, calculer l’erreur et commander la correction des coefficients du réseau pour la réduire suivant différentes stratégies de retropropagation.

Voilà comment j’ai "percu" l’évolution des réseaux de neurones ces 30 dernières années.

Alors, est ce que c’était mieux avant? Non, on arrivait péniblement à lire des chèques alors qu’à présent les réseau de neurones génération tels gpt3 sont capable de tenir une conversation avec un humain sans qu’il s’en rende compte. Je passe outre les nombreux autres exploits de certaines architectures permettant le deepfake vidéo ou audio. Ils sont nombreux.

Par contre l’exemple utilisé sur c64 me laisse perplexe. Les réseaux ne sont pas faits pour calculer péniblement une approximation de fonction. Pour cela l’ingénierie possède déjà toutes les techniques mathématiquement éprouvées.

Vouloir faire cela montre une mauvaise séparation entre l’IA et l’Algorithmique (je connais bien les deux, c’était le sujet de mon DEA). Et ça c’est très dangereux pour la société. Cette méconnaissance entre les deux domaines est dorénavant patente lorsque des journalistes évoquant tel ou tel exploit technologique disent que c’est grâce aux "algorithmes" en lieu de reseaux profonds neurones. Je t’en foutrais de l’algorithme quand personne ne comprends finement pourquoi un réseau marche ou pas....

Du coup les recruteurs qui demandent â un candidat programmeur d’écrire un algorithme pour résoudre FizzBuzz tombent sur ce genre de discussions
Recruteur: Welcome, can I get you coffee or anything? Do you need a break?

Candidat: No, I've probably had too much coffee already!

R: Great, great. And are you OK with writing code on the whiteboard?

C: It's the only way I code!

R: ...

C: That was a joke.

R: OK, so are you familiar with "fizz buzz"?

C: ...

R: Is that a yes or a no?

C: It's more of a "I can't believe you're asking me that."

R: OK, so I need you to print the numbers from 1 to 100, except that if the number is divisible by 3 print "fizz", if it's divisible by 5 print "buzz", and if it's divisible by 15 print "fizzbuzz".

C: I'm familiar with it.

R: Great, we find that candidates who can't get this right don't do well here.

C: ...

R: Here's a marker and an eraser.

C: thinks for a couple of minutes

R: Do you need help getting started?

C: No, no, I'm good. So let's start with some standard imports:

Code : Tout sélectionner

import numpy as np
import tensorflow as tf
R: Um, you understand the problem is fizzbuzz, right?

C: Do I ever. So, now let's talk models. I'm thinking a simple multi-layer-perceptron with one hidden layer.

R: Perceptron?

C: Or neural network, whatever you want to call it. We want the input to be a number, and the output to be the correct "fizzbuzz" representation of that number. In particular, we need to turn each input into a vector of "activations". One simple way would be to convert it to binary.

R: Binary?

C: Yeah, you know, 0's and 1's? Something like:

Code : Tout sélectionner

def binary_encode(i, num_digits):
    return np.array([i >> d & 1 for d in range(num_digits)])
R: stares at whiteboard for a minute

C: And our output will be a one-hot encoding of the fizzbuzz representation of the number, where the first position indicates "print as-is", the second indicates "fizz", and so on:

Code : Tout sélectionner

def fizz_buzz_encode(i):
    if   i % 15 == 0: return np.array([0, 0, 0, 1])
    elif i % 5  == 0: return np.array([0, 0, 1, 0])
    elif i % 3  == 0: return np.array([0, 1, 0, 0])
    else:             return np.array([1, 0, 0, 0])
R: OK, that's probably enough.

C: That's enough setup, you're exactly right. Now we need to generate some training data. It would be cheating to use the numbers 1 to 100 in our training data, so let's train it on all the remaining numbers up to 1024:

Code : Tout sélectionner

NUM_DIGITS = 10
trX = np.array([binary_encode(i, NUM_DIGITS) for i in range(101, 2 ** NUM_DIGITS)])
trY = np.array([fizz_buzz_encode(i)          for i in range(101, 2 ** NUM_DIGITS)])
R: ...

C: Now we need to set up our model in tensorflow. Off the top of my head I'm not sure how many hidden units to use, maybe 10?

R: ...

C: Yeah, possibly 100 is better. We can always change it later.

Code : Tout sélectionner

NUM_HIDDEN = 100
We'll need an input variable with width NUM_DIGITS, and an output variable with width 4:

Code : Tout sélectionner

X = tf.placeholder("float", [None, NUM_DIGITS])
Y = tf.placeholder("float", [None, 4])
R: How far are you intending to take this?

C: Oh, just two layers deep -- one hidden layer and one output layer. Let's use randomly-initialized weights for our neurons:

Code : Tout sélectionner

def init_weights(shape):
    return tf.Variable(tf.random_normal(shape, stddev=0.01))

w_h = init_weights([NUM_DIGITS, NUM_HIDDEN])
w_o = init_weights([NUM_HIDDEN, 4])
And we're ready to define the model. As I said before, one hidden layer, and let's use, I don't know, ReLU activation:

Code : Tout sélectionner

def model(X, w_h, w_o):
    h = tf.nn.relu(tf.matmul(X, w_h))
    return tf.matmul(h, w_o)
We can use softmax cross-entropy as our cost function and try to minimize it:

Code : Tout sélectionner

py_x = model(X, w_h, w_o)

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(py_x, Y))
train_op = tf.train.GradientDescentOptimizer(0.05).minimize(cost)
R: ...

C: And, of course, the prediction will just be the largest output:

Code : Tout sélectionner

predict_op = tf.argmax(py_x, 1)
R: Before you get too far astray, the problem you're supposed to be solving is to generate fizz buzz for the numbers from 1 to 100.

C: Oh, great point, the predict_op function will output a number from 0 to 3, but we want a "fizz buzz" output:

Code : Tout sélectionner

def fizz_buzz(i, prediction):
    return [str(i), "fizz", "buzz", "fizzbuzz"][prediction]
R: ...

C: So now we're ready to train the model. Let's grab a tensorflow session and initialize the variables:

Code : Tout sélectionner

with tf.Session() as sess:
    tf.initialize_all_variables().run()
Now let's run, say, 1000 epochs of training?

R: ...

C: Yeah, maybe that's not enough -- so let's do 10000 just to be safe.

And our training data are sequential, which I don't like, so let's shuffle them each iteration:

Code : Tout sélectionner

    for epoch in range(10000):
        p = np.random.permutation(range(len(trX)))
        trX, trY = trX[p], trY[p]
And each epoch we'll train in batches of, I don't know, 128 inputs?

Code : Tout sélectionner

BATCH_SIZE = 128
So each training pass looks like

Code : Tout sélectionner

        for start in range(0, len(trX), BATCH_SIZE):
            end = start + BATCH_SIZE
            sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end]})
and then we can print the accuracy on the training data, since why not?

Code : Tout sélectionner

        print(epoch, np.mean(np.argmax(trY, axis=1) ==
                             sess.run(predict_op, feed_dict={X: trX, Y: trY})))
R: Are you serious?

C: Yeah, I find it helpful to see how the training accuracy evolves.

R: ...

C: So, once the model has been trained, it's fizz buzz time. Our input should just be the binary encoding of the numbers 1 to 100:

Code : Tout sélectionner

    numbers = np.arange(1, 101)
    teX = np.transpose(binary_encode(numbers, NUM_DIGITS))
And then our output is just our fizz_buzz function applied to the model output:

Code : Tout sélectionner

    teY = sess.run(predict_op, feed_dict={X: teX})
    output = np.vectorize(fizz_buzz)(numbers, teY)

    print(output)
R: ...

C: And that should be your fizz buzz!

R: Really, that's enough. We'll be in touch.

C: In touch, that sounds promising.

R: ...
Le candidat n’a pas eu le job. Il a pourtant testé son code chez lui. Il marche bien à quelques erreurs près. Il est toujpurs persuadé que son erreur était de ne pas avoir utilisé un réseau assez profond.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Avatar de l’utilisateur
Mokona
Messages : 1040
Inscription : 17 déc. 2016 22:01
Localisation : Nord Est des Yvelines
Contact :

Re: TensorFlow Lite for Commodore 64s

Message par Mokona »

J'ai beaucoup aimé :)

À vrai dire, pendant le sketch, je pensais que le candidat se moquait du recruteur pour avoir osé lui faire passer ce test.
__sam__
Messages : 7924
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: TensorFlow Lite for Commodore 64s

Message par __sam__ »

Tout le code python est réel. Je crois que je me suis trompé avec le tuto tf sur aws. Celui que j’ai en tête est plus simple . On y apprends comment construire un reseau différenciant des images de chat et de chiens. Le plus rigolo étant de lui présenter une image de canard qui n’a jamais fait parti de son corpus d’apprentissage. Et dire qu’on espère rendre les voitures autonomes capable de decision mettant en jeu la vie d’autrui sans responsabilité humaine nulle par.... je suis circonspect.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Fool-DupleX
Messages : 2286
Inscription : 06 avr. 2009 12:07

Re: TensorFlow Lite for Commodore 64s

Message par Fool-DupleX »

Par contre l’exemple utilisé sur c64 me laisse perplexe.
C'est exactement ce que je sous-entendais en posant la question "était-ce mieux avant ?". Il ne s'agit bien sûr pas de dire que les réseaux de neurones étaient mieux avant. Tu as parfaitement su illustrer ma pensée, à savoir le problème de la pertinence de l'approche et de la qualité du code. Le réseau de neurones de SVM n'est pas plus performant et pourtant il est diablement plus efficace et plus souple à puissance de calcul égale (peu ou prou) que ce joli Tensorflow lite.
Répondre