DevLog de Gno_

Gno

Sage
Auteur du topic
9 Nov 2022
694
1,182
Sans l'aide d'aucun moyen externe, j'ai eu l'approbation d'Edgar, et comme dit sur mon profil, à mes yeux, la réaction d'Edgar, compte pour l'infini. Ainsi, je suis en droit de faire mon topic de DevLog, et combattre la menace anarcho-gaucho qu'est Pingouin à l'aide de ma droite (fascisme) inné.

Beaucoup de projet ont été fait depuis que j'ai commencé la faculté, le premier et le plus gros, le NASpi (que vous pouvez retrouver ici), qui me sert d'unité de NAS et aussi de service VPN (pour me connecter à mon réseau local même en dehors de chez moi). Cependannnnt, c'est vraiment peu puissant :

Raspberry Pi 3B+ (celui que j'ai)Raspberry Pi 5 (le dernier d'actualité)
ProcesseurBroadcom BCM2837B0, Cortex-A53 (ARMv8, 64 bits), 4 coeurs à 1.4 GHzBroadcom BCM2712, Cortex-A76 (ARMv8, 64 bits), 4 coeurs à 2.4 GHz
RAM1 Go LPDDR2 (c'est comme de la DDR2 du coup)4 Go ou 8 Go LPDDR4X (DDR4 logiquement)
Processeur graphiqueBroadcom VideoCore IVBroadcom VideoCore VII, OpenGL ES 3.1, Vulkan 1.2

Le charabia informatique avec des composants que personne ne connait (sauf les plus néophytes), mais en gros l'un a un processeur bien plus puissant, et 4 à 8 fois plus de RAM (et encore, étant donné que la RAM du 5 est de 2 générations supérieures, c'est bien plus que ça). Mais, pour quelques opérations et actions simples ça peut être utile.


Maintenant, quand on doit faire des opérations bien plus compliquées (du transcodage vidéo avec Plex, ou autre), ça demande plus de performances. C'est pour ça que j'ai sauté sur l'occasion quand mon père m'a proposé de récupérer un vieux PC à son boulot, qui était dans un mauvais état niveau configuration. J'ai quand même tenté de le réparer (avec succès), mais le disque dur était selon moi trop endommagé après avoir tourné tout le temps pendant plusieurs paires d'années.

Comme sous-entendu dans ce topic, j'avais une configuration avec :
ProcesseurIntel Pentium G4400 (G pour Gold, car il est goldé comme processeur (non)),
2 coeurs 2 threads à 3.30 GHz
3 Mo de "smart cache Intel"
RAM1x4 Go en DDR4 (c'est vraiment bof, surtout en une seule barrette car aucun dual-channel du coup)
Stockage500 Go en HDD (qui, comme dit, devait bien être fatigué

J'ai procédé à un ravalement de façade (enfin, pas vraiment de façade, car c'était à l'intérieur...) :
Processeuri7 6700 (lui il est goldé)
4 coeurs 8 threads à 3.40 GHz, 4.00 GHz en mode turbo
8 Mo de "smart cache Intel"
RAM2x8 Go en DDR4 (bien mieux, et on peut bénéficier du dual-channel comme ça)
Stockage256 Go en SSD (SATA), ce qui est bien mieux
Et 4 To en HDD, que j'ai ajouté après en achetant un disque dur de vidéo-surveillance sur Leboncoin

Donc avec cette config, j'ai un très bon PC de serveur, qui peut faire du transcodage et bien plus (surtout quand on sait maitriser la distribution Debian en terminal, et Docker notamment, qui permet de créer des "systèmes d'exploitation" dans un espace clos, de sorte à ce qu'il ne puisse pas communiquer en dehors et casser d'autres trucs si jamais il y a un problème).

Prochaine histoire : La création d'un système de backup codé en bash (vous verrez, c'est bien compliqué, mais assez amusant)
 
Dernière édition:
  • Wow
  • Like
Réactions: 1 membres

Etoile

Génie
Plus bavard du mois
30 Oct 2024
2,106
2,125
C'est pas un peu du plagiat tout ça cher Gno ??? Bon après si le patron a dit oui, c'est que ce n'en est pas car le patron a toujours raison. Et sinon, très beau vlog.
 

Gno

Sage
Auteur du topic
9 Nov 2022
694
1,182

DevLog #2

Avant tout, une réponse à mes très chers détracteurs.

C'est pas un peu du plagiat tout ça cher Gno ??? Bon après si le patron a dit oui, c'est que ce n'en est pas car le patron a toujours raison. Et sinon, très beau vlog.
Ce n'est pas un plagiat parce que : j'ai mis un "V" majuscule et j'ai ajouté un underscore (_) dans le titre. Donc pouèt pouèt camembert c'est moi qu'a raison.


Bon
Aujourd'hui, à l'affiche de cette deuxième édition : un service de backup pour mon téléphone (je vais tâcher de ne pas trop entrer dans les détails).

Au final, pour ce DevLog, je peux tout simplement envoyer le PDF de la documentation que j'ai produite en amont et en même temps que la mise en place de ce projet, c'est vrai que ça serait plus simple et vous auriez eu 10 pages toutes construites et avec une mise en page parfaite, mais le hic c'est qu'il y a mes coordonnées et j'ai la flemme d'anonymiser (alors que ça ne prendrait que 5 minutes à faire).

Donc tout d'abord, pourquoi et comment ? C'est vrai, c'est pas tous les jours qu'on se dit "tiens, je vais faire un système de backup", d'autant plus que des solutions toutes faites existent (Google One, d'autres services Google, et j'en passe énormément), mais le premier problème majoritaire à ces solutions toutes faites c'est que c'est généralement payant. Et même si ça ne l'est pas, l'idée d'avoir mes données stockées sur un cloud d'une grande multinationale et sans aucunes certitudes qu'elles ne fuiteront pas me dérange énormément. Bon, même si dernières ont probablement déjà toutes sortes de données sur moi, et ce n'est pas mes quelques photos qui les intéresseront. Néanmoins, c'est dans une logique de "je vais moins leur en donner", et surtout de bidouille, que j'ai décidé de faire ce projet.

Mais là vous allez me dire "Ô grand Gno, mais pourquoi faire ça ?". Réponse simple : je me suis fait voler mon téléphone. Et à cause de cette erreur, j'ai perdu toutes les photos de mon chat que j'avais prises. Et je n'avais fait aucune backup de ces dernières, et pour la majorité, je ne les ai jamais envoyé au travers d'un quelconque réseau social. Je suis donc un homme en colère. Du moins, j'étais, car à chaque problème il y a une solution, d'autant plus si on sait bidouiller du Linux.

En effet, sur Linux (et aussi Android, qui a un noyau Linux) il y a énormément de choses utiles et pratiques. La première, qui se trouve sur Android, c'est ADB (pour Android Debug Bridge), qui permet de connecter un téléphone à un PC, et de le "contrôler" via ce même PC. C'est un système qui est souvent utilisé quand on fait de la programmation (programmation avec Android Studio, ou avec React), pour notamment voir le résultat sur l'écran du téléphone (et savoir si l'affichage n'est pas fucked up). Ce ADB possède deux modes de connectivité, le premier (le plus courant et le moins dangereux) via USB, et le second (qui peut être tout aussi courant mais surtout plus dangereux) via Wi-Fi, c'est ce dernier qui nous intéressera car c'est contraignant de brancher son téléphone en USB sur le serveur. (il est plus dangereux car impaginons je l'active dans un réseau publique, il sera plus simple de modifier certains paramètres du téléphone, sans qu'on s'en rende compte).

Outils principaux

Vous ai-je dit que Linux était incroyable ? Oui, mais je le redis. Sur Linux, il existe divers "applications" et outils (appelés paquets), notamment un qui se nomme adb, et qui permet d'effectuer une backup très simplement via une commande (et en ayant pensé à connecter son téléphone au PC, via l'adresse IP locale ou simplement via USB) :
Bash:
adb pull <source> <destination>

On peut décider de faire une backup intégrale du téléphone, qui sera enregistrer sous le format d'une image (image qu'on peut appliquer intégralement sur le même modèle de téléphone, pour le "dupliquer"), ou très simplement copier un répertoire précis du téléphone. Nous allons partir sur la seconde solution, qui aura le mérite d'être plus lègère et plus simple, d'autant plus que je ne veux que sauvegarder les photos et autres.

Scripts

Pour ce projet, nous utiliserons le langage Bash, qui est très populaire dans le milieu de l'automatisation sous linux, et qui permet très facilement d'exécuter des commandes qui ont été installées via des paquets. (par ailleurs, la grande majorité des commandes disponibles sous Linux ont été codées en Bash).

Le premier script à faire c'est celui pour trouver le téléphone dans le réseau. En effet, hormis si je configure le téléphone pour avoir une IP statique, l'IP du téléphone sur le réseau local pourrait changer, donc il faut trouver un moyen de récupérer l'IP dynamiquement. Et pour cela, on peut utiliser l'outil nmap (qu'il faut au préalable installer). Et grace à ce dernier, on peut lister et récupérer les informations des appareils connectés au réseau.

Maintenant, on pourrait prendre le nom du téléphone pour tenter de le faire match avec un des noms d'appareil sur le réseau. Idée intéressante et claire, mais un des problème c'est qu'il peut y avoir 2 téléphones de même nom sur le réseau.

Typiquement, dans mon cas, j'ai un Nothing Phone 2(a), avec comme nom A142, donc il suffit qu'il y ait une personne avec le même téléphone que moi (donc avec comme nom A142 aussi) pour qu'il y ait des problèmes de concurrence. La façon la plus simple de régler ce souci, c'est de prendre l'adresse MAC du téléphone, qui reste fixe.

Ainsi, on peut construire un script assez simple (dans la logique, peut-être pas dans la pratique) pour trouver le téléphone :
Bash:
#!/bin/bash

if [ $# -ne 1 ]; then
    echo "Erreur: Nombre d'arguments incorrects."
    echo "Usage: $0 <device_mac>"
    exit 1
fi

# Variables utilitaires
TARGET_PHONE_MAC=$1
NETWORK="192.168.0.0/24"
LOG="/var/log/phone_backup.log"
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")

# Fonction pour vérifier si l'IP correspond au téléphone recherché
check_phone_mac() {
    local ip=$1
    echo "[$TIMESTAMP] [INFO] [SCAN_NETWORK] - Verification of $ip..." | tee -a $LOG

    PHONE_MAC=$(sudo nmap -sn "$ip" | awk '/MAC Address/ {print $3}')
    echo "[$TIMESTAMP] [INFO] [SCAN_NETWORK] - MAC of $ip is $PHONE_MAC" | tee -a $LOG

    if [ -n "$PHONE_MAC" ]; then
        echo "[$TIMESTAMP] [INFO] [SCAN_NETWORK] - MAC address found : $PHONE_MAC" | tee -a $LOG
        if [ "$PHONE_MAC" == "$TARGET_PHONE_MAC" ]; then
            echo "[$TIMESTAMP] [INFO] [SCAN_NETWORK] - Device found: $PHONE_MAC ($ip)" | tee -a $LOG
            return 0
        else
            echo "[$TIMESTAMP] [WARNING] [SCAN_NETWORK] - $ip has a different MAC address" | tee -a $LOG
        fi
    else
        echo "[$TIMESTAMP] [ERROR] [SCAN_NETWORK] - Cannot get MAC address" | tee -a $LOG
    fi

    return 1
}

# Scan du réseau local pour trouver les IP actives
echo "[$TIMESTAMP] [INFO] [SCAN_NETWORK] - Scanning local network..." | tee -a $LOG
IP_LIST=$(nmap -sn $NETWORK | grep "Nmap scan report for" | awk '{print $NF}' | tr -d '()')

if [ -z "$IP_LIST" ]; then
    echo "[$TIMESTAMP] [ERROR] [SCAN_NETWORK] - No IP address detected on the network" | tee -a $LOG
    exit 1
fi

echo "[$TIMESTAMP] [INFO] [SCAN_NETWORK] - IP addresses detected :" | tee -a $LOG
echo "$IP_LIST" | tee -a $LOG

# Parcourir chaque IP trouvée et vérifier si c'est le bon téléphone
for ip in $IP_LIST; do
    check_phone_mac "$ip"
    if [ $? -eq 0 ]; then
        echo "[$TIMESTAMP] [INFO] [SCAN_NETWORK] - Targetted phone found on IP : $ip" | tee -a $LOG
        exit 0
    fi
done

echo "[$TIMESTAMP] [ERROR] [SCAN_NETWORK] - Targetted phone ($TARGET_PHONE_MAC) not found" | tee -a $LOG

La seconde commande à coder c'est simplement une récupération de l'IP avec la commande précédente, puis une succession de copie des répertoires du téléphone.
Bash:
#!/bin/bash

# Définition des variables
BACKUP_DIR="$HOME/phone_backup_docker/backups"
LOG="/var/log/phone_backup.log"
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")

echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - Starting backup..." | tee -a $LOG

# Scan du réseau pour détecter l'IP du téléphone
MAC=$(cat ~/phone_backup_docker/phone_mac.conf)
PHONE_IP=$(~/phone_backup_docker/find_device.sh $MAC | sed -n 's/.*Targetted phone found on IP : \([0-9.]\+\).*/\1/p')

if [ -n "$PHONE_IP" ]; then
    echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - Phone detected at $PHONE_IP" | tee -a $LOG

    # Connexion ADB
    adb connect "$PHONE_IP":5555 > /dev/null 2>&1
    sleep 5  # Attendre la connexion

    # Vérification de la connexion
    adb devices | grep "$PHONE_IP" > /dev/null

    if [ $? -eq 0 ]; then
        echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - Connexion success, starting backup..." | tee -a $LOG

        # Créer une sauvegarde avec un timestamp unique
        BACKUP_NAME="backup_$TIMESTAMP"
        mkdir -p "$BACKUP_DIR/$BACKUP_NAME"

        echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - Pulling Download" | tee -a $LOG
        adb pull /storage/emulated/0/Download "$BACKUP_DIR/$BACKUP_NAME/Download" | tee -a $LOG 2>&1
        echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - Download pulled" | tee -a $LOG
        echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - Pulling DCIM" | tee -a $LOG
        adb pull /storage/emulated/0/DCIM "$BACKUP_DIR/$BACKUP_NAME/DCIM" | tee -a $LOG 2>&1
        echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - DCIM pulled" | tee -a $LOG
        echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - Pulling Pictures" | tee -a $LOG
        adb pull /storage/emulated/0/Pictures "$BACKUP_DIR/$BACKUP_NAME/Pictures" | tee -a $LOG 2>&1
        echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - Pictures pulled" | tee -a $LOG
        echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - Pulling Musics" | tee -a $LOG
        adb pull /storage/emulated/0/Musics "$BACKUP_DIR/$BACKUP_NAME/Musics" | tee -a $LOG 2>&1
        echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - Music pulled" | tee -a $LOG
        echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - Pulling Documents" | tee -a $LOG
        adb pull /storage/emulated/0/Documents "$BACKUP_DIR/$BACKUP_NAME/Documents" | tee -a $LOG 2>&1
        echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - Documents pulled" | tee -a $LOG

        if [ $? -eq 0 ]; then
            echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - Backup success : $BACKUP_NAME" | tee -a $LOG
        else
            echo "[$TIMESTAMP] [ERROR] [PHONE_BACKUP] - Backup failed" | tee -a $LOG
        fi

        # Déconnexion propre
        adb disconnect "$PHONE_IP":5555

        # Supprimer les sauvegardes les plus anciennes, ne garder que les 10 plus récentes
        echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - Clean old backups..." | tee -a $LOG
        ls -1t "$BACKUP_DIR" | tail -n +11 | xargs -I {} rm -rf "$BACKUP_DIR/{}"

    else
        echo "[$TIMESTAMP] [ERROR] [PHONE_BACKUP] - ADB connexion failed" | tee -a $LOG
    fi
else
    echo "[$TIMESTAMP] [ERROR] [PHONE_BACKUP] - Phone not found in network" | tee -a $LOG
fi

echo "[$TIMESTAMP] [INFO] [PHONE_BACKUP] - End of backup" | tee -a $LOG

Pour les deux codes, on a géré les différentes erreurs possibles (téléphone pas trouvé, erreurs avec la commande, etc), et nous avons aussi fait des logs appropriés pour pouvoir mieux diagnostiquer les erreurs.


Automatisation et conteneur

Pour faire tourner ce code, nous allons utiliser Docker, qui est une sorte "d'émulateur de système d'exploitation". C'est dit très grossièrement, mais ça permet de dédier un conteneur (une boite fermée) à un service qui tournera non-stop. C'est une façon sécurisée de faire tourner un script, car si jamais il y a un problème (que le script devienne fada et qu'il casse le système d'exploitation en entier), il n'aura détruit que son conteneur et il suffira simplement de le recréer via une commande.

Nous allons aussi utiliser crontab, un outil Linux qui permet de planifier l'exécution des tâches.
Exemple :
Code:
0 3 * * 1 /$HOME/phone_backup_docker/scripts/backup.sh >> $HOME/phone_backup_docker/logs/phone_cron.log
Ici, on exécute la commande:
  • le jour 0 de la semaine (lundi)
  • à 3h
  • * = on s'en fout
  • * = on s'en fout

Vient ensuite Docker, et sans entrer dans les détails pour configurer le conteneur (car je me suis un peu arraché les cheveux), on va préciser dans un fichier "Dockerfile" (qui sert de fichier de configuration) :
  1. L'image à utiliser (dans notre cas, Debian, qui est assez lourd comparé à Alpine, mais ça permet d'avoir une meilleure compatibilité)
  2. Une commande à effectuer, pour notamment mettre le conteneur à jour, et installer les outils qu'on aura besoin, comme :
    • rsync (outil pour copier efficacement)
    • iputils-ping (dépendances pour les outils liés aux scans d'IP)
    • nmap (l'outil pour scanner le réseau)
    • bash
    • adb
  3. Une commande pour copier les scripts du PC dans le conteneur (car sinon, on y a pas accès étant donné que le conteneur est clos)
  4. Une commande pour donner une permission d'exécution aux scripts qui ont été copiés
  5. On précise aussi le répertoire de travail (le chemin où les commandes seront exécutés, c'est très important)
  6. Puis, le script à exécuter (script = crontab (qui exécutera le script avec son intervalle))

J'ai été assez évasif sur certaines choses, car parfois ce n'était pas pertinent, ou trop compliqué. J'ai aussi omis énormément de problèmes que j'ai eu, car finalement pour l'un des plus gros que j'ai actuellement, je n'ai toujours pas réussi à le régler. Mais pour avoir essayé, le script fonctionne et tout tourne comme il faut (plus jamais je ne perdrais les photos de mon chat.) !
 
Dernière édition:

Gno

Sage
Auteur du topic
9 Nov 2022
694
1,182

DevLog #2.5

Un DevLog plus court, peut-être moins informatique mais je vais relayer ce que j'ai pu faire aujourd'hui.


1. Le PC bricolé

Plus haut dans ce topic, j'ai dit que j'avais acheté un PC en entier car ça coutait tout aussi cher qu'acheter le processeur séparément. J'ai un peu attendu avant de le booter etc, car il me fallait un SSD pour le faire fonctionner, SSD que j'ai récupéré en défonçant un SSD externe pour récupérer la petite carte à l'intérieur.

J'attendais de recevoir la commande Aliexpress que j'avais faite, car il y avait justement un adaptateur en SATA pour cette petite carte, afin que je puisse le connecter au PC, et j'ai reçu tout ça aujourd'hui. En soi, tout fonctionne, c'est ce qu'il me fallait. La prochaine étape c'est l'installation de Debian (j'ai déjà une clé USB bootable avec un Debian dessus, donc c'est 15 minutes d'économisé). J'allume le PC, après un peu de galère, je rentre dans un des nombreux menus UEFI, et j'ai une page ressemblant à un pré-BIOS. Je choisis l'option pour aller dans le BIOS et là :
IMG_20250201_172556793.jpg
(faites pas attention au bureau.)

Donc en gros : Le vendeur m'a vendu un PC avec un mot de passe qui m'empêche d'accéder au BIOS (donc je ne peux même pas désactiver le secure boot).
La solution la plus simple c'est de contacter le vendeur (ce que j'ai fait), en espérant avoir une réponse positive.

Maintenant, si jamais je n'ai pas de réponse, la dernière chose à faire c'est de l'éteindre, le débrancher, vider les condensateurs et retirer la pile CMOS pendant 30 minutes pour espérer reset la mémoire de la carte mère. Maintenant j'ai pas beaucoup d'espoir pour cette solution car ça a été "patch" pour les PC professionnels (et c'est justement ce type de PC que j'ai).


2. NFC et compagnie

Dans le lot Aliexpress que j'ai commandé, j'ai aussi reçu mes tags NFC. C'est une connerie qui coute 2€ (les 20), mais j'ai toujours voulu en avoir pour rigoler un peu. Pour ceux qui ne savent pas ce que c'est, c'est des puces sans fils (généralement sous la forme d'une carte), qui permettent d'accéder à une page internet ou autre. C'est souvent utilisé (à l'heure d'aujourd'hui) dans les restaurants pour avoir les cartes avec le téléphone.

J'ai premièrement fait un tag qui m'ouvre Waze sur mon téléphone, et vous allez me demander "mais pourquoi Gno ?". En fait je l'ai mis sur le support de téléphone dans ma voiture, comme ça, quand je le mets dessus, ça m'ouvre Waze et j'ai plus qu'à entrer la destination que je veux. (bon l'idée est géniale mais dans la pratique c'est pas parfait).

Pour la deuxième utilisation, je me suis muni de mon meilleur logiciel de modélisation, et j'ai modélisé un petit truc rapidement. Je l'ai imprimé, j'ai tout monté, peint et voici le résultat :
IMG_20250201_184105716.jpgIMG_20250201_184326276.jpgIMG_20250201_221551410.jpg
(pour ceux qui ne reconnaitrait pas, c'est un badge qui ouvre une page vers mon GitLab.)

Au prochain épisode : probablement la réponse du vendeur (si elle est négative je pète mon crâne, mais au moins ça vous sera peut-être plus divertissant de me voir en train de galérer avec un PC).
 
Dernière édition:
  • Like
  • Wow
Réactions: 1 membres

Gno

Sage
Auteur du topic
9 Nov 2022
694
1,182

DevLog #3

Au programme : Aucune réponse de la part du vendeur.
Mais pour vous consoler : de la programmation !

_______________________


J'ai décidément énormément de problèmes dans ma vie, et l'un d'entre eux c'est d'avoir énormément de vinyles. J'aime la musique, c'est vrai, et c'est plaisant d'avoir des disques à mettre sur une platine vinyle, mais quand on commence à en avoir trop, c'est compliqué de choisir efficacement, sans passer 5 minutes à chercher. Et comme vous avez vu en haut, j'ai pas mal bidouillé avec les tags NFC, et en fait je me suis rendu compte que c'était bien plus intéressant et puissant quand on avait un serveur pour héberger tout sorte de site.

La solution à mon problème est simple : coder un site qui me donne aléatoirement un vinyle à écouter. Quel rapport avec le tag NFC ? Et bien je n'ai qu'à le coller sur la platine vinyle (dans un endroit pas trop dérangeant) et faire en sorte qu'il redirige mon téléphone sur la page de choix aléatoire lorsque je le scanne. Je concède, je remets pas mal ma chance sur l'aléatoire, mais dans la street on m'appelle Lucky Guy (c'est complètement faux, et Pingouin peut témoigner).

En tant qu'homme minutieux, j'ai une Google Sheets où je stocke tous les vinyles que j'ai (c'est un peu comme mon inventaire), donc j'ai déjà la base de données qu'il me faut, maintenant il manque plus qu'à savoir comment la récupérer (et comme de par hasard, la librairie Pandas peut le faire, et donc oui, je vais faire tout ça en Python).

Comme dans de nombreux domaines (comme l'IA par exemple), quand on récupère des données, l'étape la plus cruciale est de nettoyer les données. Parfois c'est simple, parfois c'est compliqué, et dans mon cas c'est plutôt simple.

Ci-dessous, vous avez un screenshot de ma Google Sheets :
1738620191927.png
(n'en profitez pas pour espionner mes goûts musicaux, bande de voyeurs.)

On remarque que le filtrage est assez simple, ce qu'on veut garder c'est :
  • Les valeurs comprises entre les lignes 4 et +∞
  • Les valeurs comprises entre les colonnes 1 (colonne A) et 7 (colonne G)
  • Et le vinyle doit être en 33T (grand format)

Pour la partie code, on va considérer qu'on a un fichier avec nos accès à la Google Sheets (je ne vais évidemment pas vous donner mes accès, simplement la façon dont c'est présenté dans ledit fichier) :
Python:
SHEET_NAME = 'nom de la sheets'
SHEET_ID = 'partie de l URL entre "/d/" et "/edit?"'

Python:
  import sheets_token
  
  sheet_name = sheets_token.SHEET_NAME
  sheet_id = sheets_token.SHEET_ID
  
  
  def get_sheets(
          sheet_name: str,
          sheet_id: str,
          keepcols: list[int]=[0,1,2,3,4,5,6]
  ) -> list[dict]:
      """
      Méthode pour récupérer la Google Sheets via un lien
  
      Paramètres :
      - `sheet_name` : nom de la Google Sheets
      - `sheet_id` : id (entre /d/ et /edit?)
      - `keepcols` : colonnes à garder
  
      Retourne une liste de dictionnaires (`list[dict]`) sous forme d'un `dataframe` (**Pandas**)
      """
      
      # Lien spécifique pour que pandas récupère la sheet
      url = f"https://docs.google.com/spreadsheets/d/{sheet_id}/gviz/tq?tqx=out:csv&sheet={sheet_name}"
      # Lecture du Google Sheets
      df = pd.read_csv(url, skiprows=[1], usecols=keepcols)
  
      # Nettoyage des noms de colonnes : suppression des espaces et des accents
      df.columns = [unidecode(col).strip().replace(' ', '_') for col in df.columns]
  
      data = df.to_dict(orient="records") # data = tableau avec tous les vinyles = vinyls
      res = []
      for d in data:
          if d.get("Format","") == "33T":
              res.append(d)
      return res

Nous avons une autre fonction, qui permet de récupérer l'image de l'album. Pas la peine de s'y attarder, c'est du simple requêtage d'API.
Python:
    def get_album_cover(artist, album):
        """ Récupère la jaquette d'un album via MusicBrainz + Cover Art Archive """
        mb_url = f"https://musicbrainz.org/ws/2/release-group/?query=album:{album} AND artist:{artist}&fmt=json"
        
        headers = {"User-Agent": "VinylApp/1.0"}
        response = requests.get(mb_url, headers=headers)
    
        if response.status_code == 200:
            data = response.json()
            if "release-groups" in data and data["release-groups"]:
                mbid = data["release-groups"][0]["id"]
                return f"https://coverartarchive.org/release-group/{mbid}/front"
    
        return "static/default.jpg"


Partie peut-être plus intéressante : le back de l'application web
Pour cette partie, j'ai décidé de faire ça en Flask, qui permet de coder une application web en Python. Il n'y a pas que Flask qui permet cela, il y a aussi FastAPI, et encore bien d'autre, mais j'ai décidé d'utiliser Flask.

Avec Flask, pour définir une route (un chemin, un url) vers une certaine partie de l'application, nous avons juste à mettre une ligne de code avant la définition de la fonction :
Python:
@app.route("/is_that_cool")
def test():
   return jsonify("some random shit yk") # jsonify est utilisé pour renvoyer une "page json" à la place de l'URL, vous verrez l'utilité après

Ainsi, dans notre cas, on souhaite récupérer un vinyle aléatoirement lorsque nous accédons à une certaine URL, donc nous avons juste à faire :
Python:
    @app.route("/get_vinyl")
    def random_vinyle():
        vinyles = get_sheets(sheet_name, sheet_id)
        if not vinyles:
            return jsonify({"error": "No vinyls found"}); 404
        vinyle = random.choice(vinyles)
    
        cover_url = get_album_cover(vinyle.get("Artiste", ""), vinyle.get("Titre", ""))
        #print(cover_url)
        vinyle["Image"] = cover_url
        
        return jsonify(vinyle)

Bravo, vous venez de coder une API. Ce qui fait que lorsque j'accède à cette page, je récupère :
1738621528317.png

Pour le front (la page affichée), c'est presque la même logique, sauf qu'on va plutôt afficher la page sur http://192.168.0.31:5000 :
Python:
    @app.route("/")
    def home():
        return render_template("index.html")
Ici, on fait appel à une méthode spécifique de la librairie Flask. On retourne une page dite "template" (donc simplement à comprendre qu'on renvoie une page HTML custom).

L'antépénultième étape (l'avant avant dernière étape) c'est de faire un beau fichier HTML, un beau CSS (la blague, j'utilise juste TailwindCSS avec DaisyUI, j'ai pas le temps pour le CSS) et un JavaScript. Je vous épargne ça, car c'est pas très intéressant (le front-end c'est pas intéressant, mais c'est plus visuel que le back-end).

L'avant dernière étape, c'est d'exporter ça dans un conteneur Docker, pour que ça puisse tourner 24/7.

PUIS, la dernière étape : on configure le tag NFC, puis on le colle sur la platine vinyle
1738622353455.png

Et quand je scanne le tag, voici ce que j'ai :
1738622485449.png

Maintenant, les problèmes n'arrivent jamais seuls

Le premier c'était qu'il y avait trop d'appel pour récupérer la Google Sheets, et en soi pourquoi pas, mais c'est pas intéressant de la re-récupérer avec chaque chargement de la page, car la discographie ne changera pas tout le temps (je ne suis pas riche au point d'ajouter un vinyle tous les jours dedans). Donc ce que je fais, c'est que je stocke la variable contenant toute la discographie dans le cache du navigateur (et Flask permet de faire ça très simplement !)

Le second problème, toujours en rapport avec la latence avec les appels d'API. A chaque fois que je charge le lien, je fais un appel d'API (en vérité, il y en a 2) pour récupérer l'image de l'album. Et ça ne peut pas continuer comme ça, car déjà c'est quelque peu des appels inutiles, et il y a moyen de monter sa propre base de données localement, au fur et a mesure.

Pour faire simple :
  1. Je veux une image
  2. Je regarde déjà localement si je ne l'ai pas
    • Je l'ai -> je renvoie l'URL que j'ai stocké
    • Je ne l'ai pas -> je stocke l'URL que j'ai récupéré avec l'API dans un fichier

Ce qui donne comme code :
Python:
def get_local_album_cover(
        artist: str, 
        album: str, 
        date: str
)->str:
    """
    Renvoie l'url vers l'image de l'album
    Soit : 
    - On trouve l'url de l'image dans le dossier static
    - On récupère l'url de l'image avec l'API, tout en créant le fichier

    Paramètres :
    - `artist`: nom de l'artiste
    - `album`: nom/titre de l'album
    - `date`: date de sortie de l'album

    Retourne une chaîne de caractères correspondant avec l'image de l'album
    """
    cover_path = "static/covers"
    if not os.path.exists(cover_path):
        os.makedirs(cover_path)
    
    cover_name = f'{artist}_{album}_{date}'
    # Cas où le fichier existe localement 
    if os.path.exists(f'{cover_path}/{cover_name}'):
        url = ""
        with open(f'{cover_path}/{cover_name}', 'r') as input:
            url = input.read()
        return url
    # Cas où le fichier n'existe pas localement
    else:
        url = get_album_cover(artist, album)
        with open(f'{cover_path}/{cover_name}', 'w') as output:
            output.write(url)
        return url



_______________________

Et voila, c'est fini !

Au prochain épisode : on espère une réponse de la part du vendeur...
 

Edgar

Administrateur
Membre du personnel
11 Sept 2001
1,057
1,796
Avec un peu de retard, pour le backup de ton téléphone, un logiciel comme PhotoPrism sur ton VPS aurait pas fait l'affaire (pour backup les photos en tout cas) ?
Je m'y connais pas plus que ça mais ça me semble plus simple que de backup l'entièreté du tel avec adb (et tu peux voir tes images depuis d'autres appareils en bonus).
 

Gno

Sage
Auteur du topic
9 Nov 2022
694
1,182
Avec un peu de retard, pour le backup de ton téléphone, un logiciel comme PhotoPrism sur ton VPS aurait pas fait l'affaire (pour backup les photos en tout cas) ?
Je m'y connais pas plus que ça mais ça me semble plus simple que de backup l'entièreté du tel avec adb (et tu peux voir tes images depuis d'autres appareils en bonus).
Alors je connaissais pas-
Et pour mon truc de backup, je fais pas une backup sur l'entièreté du téléphone justement

Post scriptum: je viens de regarder photoprism, et c'est assez stylé, donc je vais peut-être un peu plus regarder tout ça et peut-être tenter un Docker (ça ne me coûte rien d'essayer, si ce n'est du temps)
 

Edgar

Administrateur
Membre du personnel
11 Sept 2001
1,057
1,796
Alors je connaissais pas-
Et pour mon truc de backup, je fais pas une backup sur l'entièreté du téléphone justement
Je vois je vois, j'ai juste survolé les derniers messages donc j'ai loupé les détails x)
Je pense m'acheter moi aussi (plutôt racheter vu que le mien est en France) un Raspberry un de ces 4, j'ai bien envie d'un petit serveur avec backup de mes photos, home assistant...
 

Gno

Sage
Auteur du topic
9 Nov 2022
694
1,182
Je vois je vois, j'ai juste survolé les derniers messages donc j'ai loupé les détails x)
Je pense m'acheter moi aussi (plutôt racheter vu que le mien est en France) un Raspberry un de ces 4, j'ai bien envie d'un petit serveur avec backup de mes photos, home assistant...
En vrai, essaie de voir si c'est pas mieux un vieux PC fixe plutôt qu'un Raspberry (rapport consommation/performance, etc). Après au niveau de l'occasion ça doit probablement être abordable un Raspberry Pi, mais je sais que neuf (et surtout les derniers) c'est un des grands problèmes, genre le 5 qui est à 94€ (8 Go de RAM, je suis pas fou hein, après y'a une version avec 16 si tu veux...)
(source: https://www.kubii.com/fr/cartes-nan...2-raspberry-pi-5-3272496315938.html#/ram-8_gb)

Toujours sur le même site, le 4B est à 87€, donc à voir (après tout dépend de ce que tu as besoin, de l'encombrement, consommation, etc)
 

Edgar

Administrateur
Membre du personnel
11 Sept 2001
1,057
1,796
En moyenne les prix sont les mêmes ici pour les Raspberry, mais pour le rapport prix/taille/consommation/performance, je suis pas sûr qu'il y en ait beaucoup qui puissent le battre. Après si je partais là dessus ce serait avec 8gb et un SSD NVMe (vu que c'est supporté par le 5).
 

Gno

Sage
Auteur du topic
9 Nov 2022
694
1,182
Ouais, parce qu'après, prendre du 16Gb sur un Raspi (même le 5), c'est pas le mieux (car il faut que le processeur ne bride pas la RAM) et c'est pas ce qui va le rendre plus puissant. Tandis que mettre un petit NVMe, ça peut permettre d'avoir une meilleure bande passante
 

Edgar

Administrateur
Membre du personnel
11 Sept 2001
1,057
1,796
En soit j'ai pas prévu de faire quoi que ce soit de graphique (UI, AI...), donc ça devrait suffire. Et un SSD c'est réutilisable donc pas de perte même si je change.
J'avais le 3b+ 1gb donc n'importe quoi sera une bonne upgrade.
 

Gno

Sage
Auteur du topic
9 Nov 2022
694
1,182

DevLog #3.2.4b

Petit DevLog rapide, plus en mode état des lieux :
  • Toujours pas de réponse du vendeur, mais il a vu.
  • J'ai voulu essayer pas mal de trucs aujourd'hui, notamment voir pour essayer PhotoPrism (car c'est très très stylé) et réinstaller un serveur VPN tout beau (car celui sur le NASpi est dead)
    • J'ai bien lu la doc de PhotoPrism et en vrai c'est pas tant compliqué à configurer
      • Mais je n'ai rien pu faire de plus
    • J'ai galéré toute la journée à réinstaller le VPN sur le gros PC, alors que l'erreur était conne :
      • Le port sur le routeur était encore configuré pour le NASpi et pas l'autre PC... (j'ai corrigé ça à l'instant)
        • MAISSSS : ça fonctionne, j'ai accès à tous sur mon réseau local, et c'est plutôt amusant de pouvoir accéder à OMV, etc hors du réseau
(j'ai abusé sur les indentations de liste non ?)

Et sur ce : bonne nuit.
 
  • Like
Réactions: 1 membres

Gno

Sage
Auteur du topic
9 Nov 2022
694
1,182

DevLog #3.82

Toujours quelque chose de rapide, car j'ai pas grand chose à dire.

Comme dit dans le DevLog #3.2.4b, le vendeur a vu mon message, mais il ne m'a pas répondu. J'en conclus que c'est un vile malandrin, mais je m'en doutais, car pour répondre un "Bonjour non" à une de mes questions, il faut vraiment être un salaupiot.

J'ai donc retiré la pile CMOS pendant près d'une heure, et contre toute attente, en le rallumant et en tentant d'aller sur le BIOS :
Il y toujours le mot de passe d'activé.

A partir de là, je n'ai pas trop su quoi faire. Mais en analysant la configuration, j'ai vu un jumper (mais qu'est-ce qu'un jumper ? c'est un pin qui vient "court-circuiter" deux pins ensemble, c'est une sorte d'interrupteur en gros). En soi, je m'en fiche un peu (mais généralement c'est pas anodin un jumper dans un PC), cependant, il y avait une curieuse indication à côté :
1738866446234.png
(oui y'a un peu de poussière.)

PSWD mais quelle est cette incantation ?? Ca veut juste dire "PASSWORD". Donc je l'ai retiré, j'ai rallumé le PC en ayant branché la clé USB bootable, et ta-daa~
1738866964436.png

Sur ce, à une prochaine, je vais installer Sunshine du coup.
 
  • Like
Réactions: 1 membre

Gno

Sage
Auteur du topic
9 Nov 2022
694
1,182
Qu'est-ce que c'est poussiéreux ici. Je vais passer un coup de balai puis on pourra passer au

DevLog #4

Et au programme de l'administration système et du rétrogaming on va faire de l'IA, donc sortez vos crayons, il y aura un peu de mathématiques.


Introduction

Contexte

J'ai récemment vu des vidéos de quelqu'un sur Instagram faire ce petit projet de réseau de neurones qui reconnaît les chiffres écrits, et je me suis dit que ça pouvait être une bonne idée. Bien que ce soit un projet très simple, il reste très intéressant pour comprendre comment fonctionne un réseau de neurones, et il peut être assez utile dans certains cas car ça reste quelque chose qui est au coeur de nombreuses choses.

Objectif du projet

L'objectif est assez simple : implémenter un réseau de neurones multicouches (MLP) from scratch avec NumPy et sans Tensorflow (sauf pour le dataset d'entraînement, mais nous n'utiliserons pas les fonctions pour nous simplifier la tâche).

Donc les contraintes sont claires : pas de TensorFlow, PyTorch, ni Scikit-learn pour le modèle.


Mise en place

Présentation du dataset

Avant de commencer, nous allons voir à quoi ressemble le dataset que nous allons utiliser pour l'entraînement. C'est une étape primordiale pour ce type de projet, étant donné que la données est au coeur même de l'IA, donc nous devons savoir avec quoi nous travaillons.

Le dataset NMIST de Tensorflow est composé de :
  • 70 000 images de chiffres manuscrits (28x28 pixels)
  • 60 000 pour l'entraînement + 10 000 pour le test

Le dataset est composé d'images, chacune avec une étiquette (label) :
  • Images : niveaux de gris (valeurs 0–255)
  • Étiquettes : entiers de 0 à 9

Architecture du réseau

Type de modèle : Perceptron multicouche (MLP)
  • Couche d'entrée : 784 neurones
  • Couches cachées : nombre de neurones variable (ex: 128)
  • Couche de sortie : 10 neurones (1 par chiffre)

Fonctions d'activation
  • ReLU pour les couches cachées
    • Rectified Linear Unit
    • fonction d'activation utilisée dans les réseaux de neurones pour ajouter de la non-linéarité
    • Défini par la formule :
      • 1742568830903.png
    • L'utilisation de ReLU permet un apprentissage plus rapide (pas d'exponentielle, juste une comparaison) et stable
    • Problème de Dead Neurons : Si un neurone reçoit toujours des valeurs négatives, sa sortie est toujours 0 et il n'apprend plus

  • Softmax pour la sortie
    • Interprétation probabiliste, transformation des vecteurs scores en distribution de probabilités
    • Permet d'utiliser les résultats plus facilement
    • Défini par la formule :
      • 1742569082955.png

Pour l'initialisation des poids (le "premier tour"), nous allons simplement la mettre aléatoirement, elle se corrigera ensuite toute seule.

Entraînement du réseau

Pour l'entraîner, nous allons utiliser la méthode du cross-entropy loss, ce qui veut dire qu'on va analyser les réponses des noeuds, puis pénaliser les mauvaises prédictions en ajustant les poids des noeuds.

Pour l'image du réseau de neurones, imaginez 10 personnes qui ont une tâche spécifique : trouver un nombre (la personne 1 cherchera si c'est un 1, la personne 2 si c'est un 2, jusqu'à la personne 10 qui cherchera si c'est un 0). Il y a une autre personne en plus dans ce réseau de neurones, c'est un peu comme le manager, il va regarder les résultats et gronder ceux qui vont se rater et pas ceux qui ont réussi. Le manager ne va pas donner d'indice, c'est le réseau de neurones qui va y aller petit à petit, en tatonnant et en cherchant les correspondances entre les différents résultats (les probabilités sortantes).

Ce qui va permettre de "propager l'erreur" et de modifier les poids des noeuds, c'est le backdrop qui va (sans entrer dans les détails) calculer les dérivées pour chaque couche, et donc propager l'erreur et modifier les poids des noeuds en conséquences, un peu comme une grande machine avec plein de molettes, où on viendrait modifier petit à petit les paramètres en tournant ces molettes pour avoir le résultat qu'on veut.

Pour l'entraînement de notre réseau nous avons différents paramètres sur lesquels nous pouvons jouer :
  • epoch : c'est le nombre d'itérations où notre réseau va s'entrainer
  • alpha: c'est le taux d'apprentissage, la taille des pas que le modèle va faire pour ajuster ses poids
    • Si on met un alpha très petit, les pas seront très petits, et ça sera plus stable, mais l'entrainement sera très long
    • Si on met un alpha suffisamment grand, les pas seront très grand, donc l'apprentissage très rapide
Maintenant que nous avons un modèle fonctionnel, on va sortir des données et faire des graphes pour observer les différences quand on change les valeurs du alpha.

Résultats

Alpha basique (0.1)

Code:
Début de l'entrainement...
Epoch 0, Loss: 2.3031
Epoch 100, Loss: 0.9512
Epoch 200, Loss: 0.5045
Epoch 300, Loss: 0.4051
Epoch 400, Loss: 0.3616
Epoch 500, Loss: 0.3355
Epoch 600, Loss: 0.3167
Epoch 700, Loss: 0.3018
Epoch 800, Loss: 0.2892
Epoch 900, Loss: 0.2779
Epoch 1000, Loss: 0.2676
Epoch 1100, Loss: 0.2580
Epoch 1200, Loss: 0.2490
Epoch 1300, Loss: 0.2405
Epoch 1400, Loss: 0.2325
Epoch 1500, Loss: 0.2250
Epoch 1600, Loss: 0.2179
Epoch 1700, Loss: 0.2111
Epoch 1800, Loss: 0.2047
Epoch 1900, Loss: 0.1986
1742570806212.png

Alpha 2x plus grand (0.2)

Code:
Début de l'entrainement...
Epoch 0, Loss: 2.3031
Epoch 100, Loss: 0.5059
Epoch 200, Loss: 0.3619
Epoch 300, Loss: 0.3169
Epoch 400, Loss: 0.2894
Epoch 500, Loss: 0.2678
Epoch 600, Loss: 0.2491
Epoch 700, Loss: 0.2327
Epoch 800, Loss: 0.2180
Epoch 900, Loss: 0.2049
Epoch 1000, Loss: 0.1930
Epoch 1100, Loss: 0.1824
Epoch 1200, Loss: 0.1727
Epoch 1300, Loss: 0.1640
Epoch 1400, Loss: 0.1562
Epoch 1500, Loss: 0.1490
Epoch 1600, Loss: 0.1424
Epoch 1700, Loss: 0.1363
Epoch 1800, Loss: 0.1306
Epoch 1900, Loss: 0.1254
1742570921178.png

Constat

Nous remarquons qu'en ayant doublé la valeur de l'alpha par 2 nous avons pas doublé les résultats. Cependant, le modèle s'est affiné bien plus vite, voire plus que quand l'alpha était à 0.1.

Alpha 4x plus grand (0.4)

Code:
Début de l'entrainement...
Epoch 0, Loss: 2.3031
Epoch 100, Loss: 0.3643
Epoch 200, Loss: 0.2851
Epoch 300, Loss: 0.2433
Epoch 400, Loss: 0.2118
Epoch 500, Loss: 0.1876
Epoch 600, Loss: 0.1681
Epoch 700, Loss: 0.1521
Epoch 800, Loss: 0.1388
Epoch 900, Loss: 0.1273
Epoch 1000, Loss: 0.1175
Epoch 1100, Loss: 0.1090
Epoch 1200, Loss: 0.1015
Epoch 1300, Loss: 0.0949
Epoch 1400, Loss: 0.0889
Epoch 1500, Loss: 0.0837
Epoch 1600, Loss: 0.0789
Epoch 1700, Loss: 0.0746
Epoch 1800, Loss: 0.0707
Epoch 1900, Loss: 0.0671
1742571041600.png

Alpha 6x plus grand (0.6)

Code:
Début de l'entrainement...
Epoch 0, Loss: 2.3031
Epoch 100, Loss: 0.3054
Epoch 200, Loss: 0.2282
Epoch 300, Loss: 0.1848
Epoch 400, Loss: 0.1558
Epoch 500, Loss: 0.1349
Epoch 600, Loss: 0.1189
Epoch 700, Loss: 0.1060
Epoch 800, Loss: 0.0954
Epoch 900, Loss: 0.0865
Epoch 1000, Loss: 0.0790
Epoch 1100, Loss: 0.0726
Epoch 1200, Loss: 0.0670
Epoch 1300, Loss: 0.0621
Epoch 1400, Loss: 0.0577
Epoch 1500, Loss: 0.0539
Epoch 1600, Loss: 0.0504
Epoch 1700, Loss: 0.0473
Epoch 1800, Loss: 0.0445
Epoch 1900, Loss: 0.0419
1742571118571.png

Conclusion

Pour mieux se rendre compte des différences, nous allons superposer les différentes courbes :
1742571154282.png

C'est subtil, mais nous pouvons observer que la tendance fait que si nous augmentons encore l'alpha, ça risque de stagner à un moment, et il semblerait que 0.6 soit le meilleur compromis.

De plus, le risque d'avoir un alpha trop élevé c'est de faire tellement des trop grands pas au point qu'on passe le bon résultat sans même le savoir, et donc d'avoir un modèle trop lent.

Un des points d'amélioration, qui est d'ailleurs la norme dans l'apprentissage automatique aujourd'hui, c'est de commencer avec une valeur d'alpha grande au début pour dégrossir le travail très rapidement, puis de passer à une valeur plus petite pour affiner le modèle.


Mise en application

A l'heure où j'écris ça (21/03/2025, 16h33), je n'ai pas encore codé la partie pour écrire un chiffre dans une fenêtre pour le détecter, mais ça va se faire assez rapidement avec une boucle while et TKinter.

Re (21/03/2025, 19h47), j'ai fait le pannel Tkinter, avec quelque chose de basique, et voici le résultat :
1742582923562.png
Impressionnant n'est-ce pas ? Et bien pas tant que ça, j'ai menti, car il marche de manière approximative. Plusieurs raisons à cela (sur ou sous-entrainement, ce que j'écris n'est pas adapté par rapport au dataset MNIST, trop de "déformations humaines", etc.).

Malheureusement, je ne peux rien faire de plus que de l'entraîner bien plus, et pour cela, j'ai paraléllisé tout le programme. Nous n'utilisons plus NumPy, mais JAX (notamment le module jax.numpy) qui permet de paralléliser tous les calculs de manière assez simplifié. Comme ça, je ne fais plus du monoprocesseur mais du multiprocesseur (avec 8 coeurs), ce qui permet d'être plus efficace.

En plus de ça, je fais du batching (je découpe les charges de travail) pour avoir plus de parties mais moins grosses, ce qui évite de surcharger la RAM (et d'aller au delà des 8Go que j'ai).

Bien sûr, nous nous éloignons des réseaux de neurones, mais qui dit IA dit forcément parallélisation, donc j'aurai tôt ou tard dû passer par là.


Conclusion et suite

J'ai pas grand chose à dire, si ce n'est que j'ai pu apprendre pas mal de chose et surtout des subtilité avec le parallélisme. Le modèle est actuellement en train d'apprendre, donc je vais probablement faire une suite d'ici peu (ce soir avec un peu de chance).
 
  • Love
Réactions: 1 membre

Etoile

Génie
Plus bavard du mois
30 Oct 2024
2,106
2,125
Je suis heureuse de vous annoncer que je n'y comprend rien. De rien, mon intervention était très utile.
 
  • Like
Réactions: 1 membre

Gno

Sage
Auteur du topic
9 Nov 2022
694
1,182

Ah euh je... Ouais.

1742896938237.png

Edit1 : On voit pas, mais c'est mieux
1742897952901.png

Edit2 : Je fais de l'art
1742899324899.png
Messages fusionnés :

J'AI REUSSI PTN

1742900452847.png

 
Dernière édition:
  • Haha
  • Lune
Réactions: 1 membres

Gno

Sage
Auteur du topic
9 Nov 2022
694
1,182
C'est leur du du-du-du-duel DevLog !

DevLog #4.1

Au programme, rapide, pas de machine learning, de script d'automatisation pour Fusion360.
Par contre j'ai fait quelques trucs cool.

J'ai vu passer ce projet : https://www.printables.com/model/1019283-project-igor-open-source-offline-loyal-cheerful-fo
Et j'ai voulu le reproduire.

Donc je vais skip les galères au niveau de l'écran chinois non officiel, où j'ai du me démerder pour trouver les bonnes adresses mémoires que l'écran prenait.
Mais après un prototypage :
1743105625739.png

Maintenant je sais que ça fonctionne (malgré les problèmes que j'avais, qui étaient dus au fait que j'avais la flemme de souder les pins sur le Wemos D1), on peut passer aux vraies soudures.

Malheureusement, je n'ai pas de photo avant montage, mais sachez que j'en ai eu marre de l'odeur de l'étain et des soudures qui lâchaient (malgré le fait que je les faisais plutôt bien pour une fois). Par contre j'ai une photo de la pire des étapes l'emboitement de tout ça. Car entre le potentiomètre, les fils, et la puce, c'était une véritable horreur de tout mettre (j'ai d'ailleurs cassé une soudure, et heureusement que j'ai vu ça avant de tout mettre).

1743106375491.png
(faites pas gaffe à l'appart en désordre)

J'ai dû remodéliser la façade avant, car ça n'allait pas (maudits écrans chinois à 1€), et après ça j'ai pu tout finaliser :
1743106759441.png
(faites pas gaffe au bureau)

BIEN, VOILA DE FAIT

Second truc, j'ai reçu un vinyle, et quand j'ai voulu l'écouter j'ai été étonné de ne pas reconnaitre la voix de mes chanteuses préférées, mais aussi un son très inquiétant quand je mettais la platine vinyle à "45 tours par minute". Un bruit de "clac" régulier.

J'ai démonté la platine, c'était assez rapide, et en changeant le mode en regardant le mécanisme, j'ai vite compris.
1743107092889.png

Le pignon où la courroie passe, c'est ça qui fait le changement entre la vitesse 33 et la vitesse 45. Quand on appuie sur le bouton de la platine, ça vient (avec des tringles) faire monter la courroie, la faisant passer par dessus les ailettes du pignon (et donc elle remonte en haut et passe sur un axe plus gros). Sauf que ça passait pas bien en haut, donc y'avait un bruit relatif à l'ailette qui tentait de la pousser en haut, mais la courroie qui ne voulait pas. Donc je l'ai simplement forcé à l'arrêt, et maintenant, même si je change la vitesse, tout se passe comme prévu.

Et le vinyle à un meilleur son, je l'aime beaucoup (surtout c'est un maxi-45, et ça c'est stylé)
 
  • Love
Réactions: 1 membre