# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # Machine Learning Client
#
# This is a rudimentary client that trains a ML model on sensor data. It is used in three steps:
#
#
# * **Training Data Recording Phase** 
#
# The client receives some sensor data from PureData along with a to-be-predicted label in the last position of the list from PureData. 
#
# * **Training Phase** 
#
# A ML model is then learned on that data to predict the labels provided during the training process
#
# * **Prediction Phase** 
#
# Finally the client uses the learned ML model to predict one of the learned categories from new sensor data. The prediction is sent via UDP in OSC format to PureData

# ## Training Data Recording

# This should not be necessary, but in case the libraries are not installed, 
# !pip install -r requirements.txt

# +
import socket
import numpy as np

localIP     = "127.0.0.1"
localPortData   = 20007

bufferSize  = 64

# Create a datagram socket
UDPServerSocketData = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)

# Bind to address and ip
UDPServerSocketData.bind((localIP, localPortData))
# UDPServerSocketData.settimeout(2)
print("UDP Data server up and listening")

def parse_message(msg):
    return [float(x) for x in msg.strip().strip(';').split(" ")]

data_and_labels = []

fh = open(f'recording-training-data-{np.random.randint(0,1000)}.txt','w')

# Listen for incoming datagrams
try:
    while(True):
        messageData, addressData = UDPServerSocketData.recvfrom(bufferSize)
        fh.write(messageData.decode())
        data_and_labels.append(parse_message(messageData.decode()))
finally:
    UDPServerSocketData.close()
    fh.close()
# -

data_and_labels

# ## Training ML Model
#
# Replace the (rather simple) [NearestCentroid Classifier](https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.NearestCentroid.html) with [any sklearn classifier](https://scikit-learn.org/stable/supervised_learning.html)

from sklearn.neighbors import NearestCentroid
from sklearn.metrics import classification_report
Xy = np.array(data_and_labels)
X, y = Xy[:,:-1], Xy[:,-1]
clf = NearestCentroid().fit(X,y)
print(classification_report(y, clf.predict(X)))

# ## Prediction Phase

# +
from pythonosc import udp_client
localPortPrediction = 7001
serverAddressPort   = (localIP, localPortPrediction)
osc_client = udp_client.SimpleUDPClient(*serverAddressPort)

# Create a datagram socket
UDPServerSocketData = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)

# Bind to address and ip
UDPServerSocketData.bind((localIP, localPortData))
print("UDP Data server up and listening")

# Create a datagram socket
UDPClientSocketPrediction = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)

print("UDP Prediction client ready")

fh = open(f'recording-during-prediction-{np.random.randint(0,1000)}.txt','w')
# Listen for incoming datagrams
try:
    while(True):
        message, address = UDPServerSocketData.recvfrom(bufferSize)
        fh.write(message.decode())
        prediction = clf.predict([parse_message(message.decode())[:-1]])[0]
        bytesToSend = str.encode(f"{prediction}")
        print(f"data {message} prediction {prediction}")
        # send prediction to server
        osc_client.send_message("/prediction", prediction)

finally:
    fh.close()
    UDPServerSocketData.close()
    UDPServerSocketPrediction.close()

StarcoderdataJupyterScriptsDedupFiltered