Skip to content

stephanet

Intelligence artificielle et bêtise naturelle

Je viens de finir mon tour d’horizon de l’intelligence artificielle en suivant les cours de Franck Yu https://cs50.harvard.edu/ai/2023/ sur le sujet. J’en ai retenu au moins deux choses:

  • Je n’aime pas ça, l’idée qu’un ordinateur puisse faire des choix en fonction de critères qui échappent au commun des mortels est une idée qui me déplait fortement. Principalement parce que cela donne un pouvoir démesuré à une caste de technocrates qui sont à l’origine des critères de décision.
  • La seconde dépend directement de la première: l’intelligence artificielle n’existe pas. J’entends par là que le terme d’intelligence artificielle est trompeur, car il n’y a aucune intelligence derrière, mais juste une suite d’algorithmes et de paramètres que seule cette caste de technocrates comprend.

Lorsqu’un ordinateur joue aux échecs, il se contente de profiter de son énorme puissance de calcul pour estimer tous les coups possibles aussi loin que sa puissance le lui permet, d’en estimer une valeur en fonction de critères connus (nombre et placement des pièces), puis de choisir le coup qui compte le plus de points. Il n’y aucune stratégie, aucun instinct, aucune intelligence derrière les coups d’un ordinateur, juste des calculs dans une proportion qu’aucun cerveau humain ne peut égaler.

Mais celui qui apprend, me direz-vous. L’ordinateur se contente d’enregistrer les mouvements qu’il a joué et de leur attribuer une note selon qu’il ai gagné ou perdu la partie. Il n’a plus qu’à regarder dans cette base de données la valeur des mouvements avant de jouer.

L’humain lui n’a qu’une puissance de calcul dérisoire et une mémoire de poisson rouge à côté. Il joue avec des stratégies, de l’expérience, de l’instinct. Et pourtant, malgré l’inégalité des forces, il gagne encore contre la machine. C’est cela la vraie intelligence.

Je vous vois arriver avec les réseaux de neurones. Ils apprennent à lire, à analyser une image, même une vidéo. C’est vrai, mais là aussi, il n’y a aucune intelligence. Chaque neurone dispose d’un algorithme ou il multiplie des valeurs par des poids, puis rajoute un biais qu’il a estimé en fonction d’un algorithme tout aussi simple qu’il a utilisé lorsqu’on lui a donné des valeurs de référence.

Encore une fois, cela fonctionne grace `a la puissance de calcul incroyablement élevée d’un ordinateur et malgré cela, l’ordinateur fera toujours une analyse moins bonne qu’un être humain. Il se trompera en lisant des chiffres, verra quelque chose qui n’existe pas dans une photographie. Parce qu’il n’est pas intelligent, il se contente de comparer statistiquement des données en fonction d’autres données.

Voitures et pièces détachées

Premières photos avec le Artra Lab OCULILUMEN 7.5mm F2.8 et je confirme mes premières impressions:

  • L’objectif tout en métal est beaucoup trop lourd pour le Nikon Zfc
  • Le manque de crans sur la bague de diaphragme oblige à vérifier l’ouverture régulièrement.
  • Les coins sont carrément flous et très sombres. C’est normal sur un fisheye, mais là on est sérieusement dans le cul de bouteille.

Par contre, le centre est excellent et le manque d’AF, vu la profondeur de champs gigantesque, ne dérange pas du tout.

Artra Lab OCULILUMEN 7.5mm F2.8

J’ai acquis cet objectif directement depuis le site d’Artra Lab. Artra Lab est une société basée à Hong Kong, ils ont visiblement des bureaux à Shenzhen.

Le site du constructeur est plutôt élégant et bien, la procédure en ligne se fait sans problème, paiement par Paypal. L’objectif est envoyé par transporteur UPS ou DHL dans un délai d’une semaine, il est correctement emballé et livré avec une petite housse du plus bel effet.

Premier mauvais point, dans sa déclaration aux douanes, Artra Lab a déclaré un objectif d’une valeur de 500HKD, c’est à dire moins de la moitié de la valeur de l’objectif. C’est ennuyeux parce que les douanes ont fait leur travail, ils ont vérifié et que cela m’a couté des frais et un délai de livraison supplémentaire d’ne semaine. Bref, ce n’est pas très sérieux. J’ai prévenu Artra Lab du problème, mais ils n’ont répondu à aucun email.

L’objectif fait sérieux, il est tout en métal et relativement lourd pour mon Nikon Zfc, trop lourd. La bague de diaphragme n’est pas crantée et elle bouge au moindre frottement. La bague de mise au point n’est pas mieux et aucun mécanisme pour la bloquer (ce qui serait utile vu l’immense profondeur de champs de l’objectif).

Les distortions sont moins marquées que ce à quoi on peut s’attendre d’une telle focale. Les bords sont flous. C’est un cul de bouteille, mais c’est un peu la définition du fish eye, donc rien à lui reprocher de ce côté.

Je n’achèterais pas d’autre objectifs de la marque, le manque de crans sur la bague de diaphragme est éliminatoire en ce qui me concerne. Un morceau de scotch règlera l’affaire, ce n’est pas sérieux.

Un neurone en Common Lisp

Un neurone est une fonction extrêmement simple qui prend un certain nombre de paramètres et retourne soit 0 (ou -1) soit 1 selon la valeur des arguments qui lui sont passés. Il multiplie chacun de ces argument par une valeur, additionne le tout et rajoute une constante. Si le résultat de cette opération est positive, alors il retourne 1, si elle est négative, il retourne -1.

L’intérêt de ce neurone, c’est qu’il est capable d’apprendre, c’est à dire que si on lui montre un jeu de données avec le résultat attendu, il va régler de lui même les constantes à utiliser pour sa petite opération et essayer de trouver une valeur idéale pour retourner la bonne réponse.

Ça vous intéresse, je vous suggère la lecture de la page Wikipedia et de faire vos propres recherches : https://en.wikipedia.org/wiki/Perceptron

Mon implémentation est sans doute très naïve et je suis certain qu’il existe une tonne de librairies qui le font beaucoup mieux que moi. Mais l’objectif ici est de comprendre le rouage de la chose, comment cela fonctionne. Une fois cela compris, il est certain que se tourner vers une librairie, complète, testée et optimisée est tout à fait recommandable pour faire un vrai projet en prod.



(setf data '(
	     (20 2000 1)
	     (40 1000 -1)
	     (30 3000 1)
	     (30 1000 -1)
	     (20 3000 1)
	     (40 2000 -1)
	     (40 4000 1)
	     (20 2000 -1)
	     (30 4000 1)
	     (20 4000 1)
	     (40 3000 -1)))


(defvar w '(1 1 1))

(defun magic (w x y)
  (if (> (+ (first w) (* (second w) x) (* (third w) y)) 0)
      1
      -1))


(dolist (l data)
  (format t "-----~%")
  (format t "~A~%" l)
  (let ((c (magic w (first l) (second l)))
	(alpha 0.00001))
    (format t "G/S=> ~A/~A~%" c (third l))
    
    (setf (first w)
	  (+ (first w) (*
			1
			alpha
			(- (third l) c))))
    (setf (second w)
	  (+ (second w) (*
			 (first l)
			 alpha
			 (- (third l) c ))))
    (setf (third w)
	  (+ (third w) (*
			(second l)
			alpha
			(- (third l) c))))
    (format t "~A~%" w)))
  
  
	     
      

Jouons au Tic Tac Toc

Je n’ai pas la moindre idée de comment se nomme ce jeu en Français, il s’agit de cette grille de trois sur trois ou l’on rentre des X et des O. Le premier à avoir aligné trois caractères identique a gagné la partie.

Dans ma course à la compréhension de l’Intelligence artificielle, j’ai donc décidé de m’attaquer `a ce jeu et d’implanter l’algorithme Minimax en Common Lisp.

L’ordinateur n’est pas imbattable, en fait, il suffit d’un peu de stratégie pour gagner, mais il tient quand même la partie. Je pense qu’il faudrait pondérer les coups en fonction du nombre de coups avant de gagner pour améliorer le système. Mais qu’à cela ne tienne, l’ordinateur connait les règles, il essaye de gagner et essaye de faire perdre son adversaire.

Le principle consiste tout simplement à visualiser par avance toutes les parties possibles pour chaque coup et de jouer en priorité ceux qui lui permettent d’arriver à la victoire.

Le code ci-dessous:

#!/opt/homebrew/bin/sbcl --script


(defmacro t-equal (p a b c)
  `(and
    (equal ,p ,a)
    (equal ,a ,b)
    (equal ,a ,c)))

(defun arrived (player state)
  (or
   (t-equal player (nth 0 state) (nth 1 state) (nth 2 state))
   (t-equal player (nth 3 state) (nth 4 state) (nth 5 state))
   (t-equal player (nth 6 state) (nth 7 state) (nth 8 state))
   (t-equal player (nth 0 state) (nth 4 state) (nth 8 state))
   (t-equal player (nth 2 state) (nth 4 state) (nth 6 state))
   (t-equal player (nth 0 state) (nth 3 state) (nth 6 state))
   (t-equal player (nth 1 state) (nth 4 state) (nth 7 state))
   (t-equal player (nth 2 state) (nth 5 state) (nth 8 state))))

(defun actions (state player)
  (let ((ret ()))
    (dotimes (i 9)
      (when (null (nth i state))
	(let ((node (copy-list state)))
	  (setf (nth i node) player)
	  (push node ret))))
    ret))

(defun display-board (state)
  (format t "--~%~%~A|~A|~A~%-----~%~A|~A|~A~%-----~%~A|~A|~A~%"
	  (or (nth 0 state) " ")
	  (or (nth 1 state) " ")
	  (or (nth 2 state) " ")
	  (or (nth 3 state) " ")
	  (or (nth 4 state) " ")
	  (or (nth 5 state) " ")
	  (or (nth 6 state) " ")
	  (or (nth 7 state) " ")
	  (or (nth 8 state) " ")))

(defun other-player (player)
  (if (equal player 1)
      2
      1))

(defun utility (state)
  (when (arrived 1 state)
    (return-from utility -1))
  (when (arrived 2 state)
    (return-from utility 1))
  0)

(defun arrived? (state)
  (or
   (arrived 1 state)
   (arrived 2 state)))

(defun max-value (state)
  (when (arrived? state)
    (return-from max-value (utility state)))
  (let ((actions (actions state 2))
	(l '(-99999999999)))
    (dolist (action actions)
      (push (min-value action) l))
    (reduce #'max l)))

(defun min-value (state)
  (when (arrived? state)
    (return-from min-value (utility state)))
  (let ((actions (actions state 1))
	(l '(9999999999)))
    (dolist (action actions)
      (push (max-value action) l))
    (reduce #'min l)))



(defun ask-user (state)
  (display-board state)
  (format t "From 0 to 8, where do you play ?~%")
  (let ((input (read)))
    (setf (nth input state) 1))
  state)

(defvar state '(nil nil nil nil nil nil nil nil nil))

(loop
  (when (arrived? state)
    (display-board state)
    (format t "Computer wins~%")
    (return))
  (setf state (ask-user state))
  (when (arrived? state)
    (display-board state)
    (format t "User wins~%")
    (return))
  
  (let ((actions (actions state 2))
	(temporary-state nil)
	(v -9999))
    (dolist (action actions)
      (let ((w (min-value action)))
	(when (> w v)
	  (display-board action)
	  (format t "Got ~A~%" w)
	  (setf v w)
	  (setf temporary-state action))))
    (setf state temporary-state)))


    

     
  

Prière de rue

Ce n’est pas très loin de mon quartier que s’est passé cette scène. Il est fréquent de voir des gens prier auprès d’un prêtre. Mais cette scène ou un groupe entier prie dans la rue ainsi, je ne l’avais jamais vu avant, je ne l’ai jamais revu après.