[Maki TANAKA] - Fab Futures - Data Science
Home About

< Home

4. Machine Learning¶

Assignment¶

Fit a machine learning model to your data

What I've learnt this week¶

 I try to learn about Neil's sample code with my dataset.<br>
First I put reading csv code, as all the codes need it. 
In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# === 1. Load dataset ===
df = pd.read_csv('./datasets/Wine_dataset.csv')   # Modify file name if different

Neural Networks¶

In [1]:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('./datasets/Wine_dataset.csv')

x = df[df.keys()[11]]
print(x)
#x = np.linspace(-3,3,100)

plt.plot(x,1/(1+np.exp(-x)),label='sigmoid')
plt.plot(x,np.tanh(x),label='tanh')
plt.plot(x,np.where(x < 0,0,x),label='ReLU')
plt.plot(x,np.where(x < 0,0.1*x,x),'--',label='leaky ReLU')
plt.legend()
plt.show()

plt.scatter(df[df.keys()[10]],df[df.keys()[1]],c='b')
plt.scatter(df[df.keys()[11]],df[df.keys()[1]], c='r')
#plt.plot(df[df.keys()[1]])
plt.show()
0      1.04
1      1.05
2      1.03
3      0.86
4      1.04
       ... 
173    0.64
174    0.70
175    0.59
176    0.60
177    0.61
Name: Hue, Length: 178, dtype: float64
No description has been provided for this image
No description has been provided for this image

Training¶

Jax¶

In [1]:
import jax
import jax.numpy as jnp
from jax import random,grad,jit
import pandas as pd

# -----------------------------
# ① Wine データ読み込み
# -----------------------------
df = pd.read_csv('./datasets/Wine_dataset.csv')

# Alcohol → X, Color intensity → y
X_np = df[['Alcohol']].to_numpy()

#from chatGPT
y_min = df['Color intensity'].min()
y_max = df['Color intensity'].max()

y_np = (df[['Color intensity']] - y_min) / (y_max - y_min)

X = jnp.array(X_np)
y = jnp.array(y_np.to_numpy()).reshape(-1, 1)

# 乱数キー
key = random.PRNGKey(0)

# -----------------------------
# forward
# -----------------------------
@jit
def forward(params,layer_0):
    Weight1,bias1,Weight2,bias2 = params
    layer_1 = jnp.tanh(layer_0@Weight1 + bias1)
    #layer_2 = jax.nn.sigmoid(layer_1@Weight2 + bias2)
    layer_2 = layer_1 @ Weight2 + bias2    # ← これだけでOK

    return layer_2

# loss
@jit
def loss(params):
    ypred = forward(params,X)
    return jnp.mean((ypred - y)**2)

# update
@jit
def update(params, rate=0.5):
    gradient = grad(loss)(params)
    return jax.tree.map(lambda p,g: p - rate * g, params, gradient)

# -----------------------------
# ③ パラメータ初期化(ここだけ形を修正)
# -----------------------------
def init_params(key):
    key1,key2 = random.split(key)
    Weight1 = 0.5 * random.normal(key1,(1,4))   # 入力1
    bias1 = jnp.zeros(4)
    Weight2 = 0.5 * random.normal(key2,(4,1))   # 出力1
    bias2 = jnp.zeros(1)
    return (Weight1,bias1,Weight2,bias2)

params = init_params(key)

# -----------------------------
# 学習ループ
# -----------------------------
for step in range(501):
    params = update(params, rate=0.1)
    if step % 100 == 0:
        print(f"step {step} loss={loss(params):.4f}")

# 結果
pred = forward(params, X)
jnp.set_printoptions(precision=2)
#print(jnp.c_[X, pred])
result = jnp.c_[X, pred]

print(
    jnp.vstack([
        result[:5],
        result[-5:]
    ])
)
step 0 loss=0.0389
step 100 loss=0.0389
step 200 loss=0.0389
step 300 loss=0.0389
step 400 loss=0.0389
step 500 loss=0.0389
[[14.23  0.32]
 [13.2   0.32]
 [13.16  0.32]
 [14.37  0.32]
 [13.24  0.32]
 [13.71  0.32]
 [13.4   0.32]
 [13.27  0.32]
 [13.17  0.32]
 [14.13  0.32]]

Next, I asked chatGPT to make python code of analysis of wine data using the example code.

In [4]:
import jax
import jax.numpy as jnp
from jax import random, grad, jit
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# ============================
# 1. Load Dataset
# ============================

df = pd.read_csv('./datasets/Wine_dataset.csv')

# Split into features (X) and labels (y)
X = df.drop("class", axis=1).values
y = df["class"].values

# Convert labels from 1,2,3 → 0,1,2
y = y - 1

# Standardize features (mean 0, std 1)
X = (X - X.mean(axis=0)) / X.std(axis=0)

# Convert to jax.numpy
X = jnp.array(X, dtype=jnp.float32)
y = jnp.array(y, dtype=jnp.int32)

# Split into train (80%) and test (20%)
train_size = int(len(y) * 0.8)
xtrain, xtest = X[:train_size], X[train_size:]
ytrain, ytest = y[:train_size], y[train_size:]

print("Train samples:", len(xtrain))
print("Test samples:", len(xtest))
print("Feature size:", X.shape[1])

# ============================
# 2. Hyperparameters
# ============================

input_size = X.shape[1]   # Number of features (13)
hidden_size = 32          # Hidden layer size
output_size = 3           # 3 classes
learning_rate = 0.05
train_steps = 2000

# Random key for initialization
key = random.PRNGKey(0)

# ============================
# 3. Initialize Parameters
# ============================

def init_params(key, input_size, hidden_size, output_size):
    k1, k2, k3 = random.split(key, 3)

    W1 = 0.1 * random.normal(k1, (input_size, hidden_size))
    b1 = jnp.zeros(hidden_size)

    W2 = 0.1 * random.normal(k2, (hidden_size, output_size))
    b2 = jnp.zeros(output_size)

    return (W1, b1, W2, b2)

params = init_params(key, input_size, hidden_size, output_size)

# ============================
# 4. Forward Pass
# ============================

@jit
def forward(params, x):
    W1, b1, W2, b2 = params
    h = jnp.tanh(x @ W1 + b1)   # Hidden layer with tanh activation
    logits = h @ W2 + b2        # Output layer (logits)
    return logits

# ============================
# 5. Loss Function (Cross-Entropy)
# ============================

@jit
def loss(params, x, y):
    logits = forward(params, x)
    exp = jnp.exp(logits)
    probs = exp / jnp.sum(exp, axis=1, keepdims=True)
    log_probs = -jnp.log(probs[jnp.arange(len(y)), y])
    return jnp.mean(log_probs)

# ============================
# 6. Parameter Update (Gradient Descent)
# ============================

@jit
def update(params, x, y, rate):
    grads = grad(loss)(params, x, y)
    return jax.tree.map(lambda p, g: p - rate * g, params, grads)

# ============================
# 7. Training Loop
# ============================

print("Start learning...")
for step in range(train_steps):
    params = update(params, xtrain, ytrain, learning_rate)
    if step % 200 == 0:
        print(f"step {step}, loss={loss(params, xtrain, ytrain):.4f}")

# ============================
# 8. Evaluate on Test Data
# ============================

logits = forward(params, xtest)
pred = jnp.argmax(logits, axis=1)
accuracy = jnp.mean(pred == ytest)

print("\n=== Test Accuracy ===")
print(f"Accuracy: {accuracy * 100:.2f}%")

# ============================
# 9. Show Sample Predictions
# ============================

print("\n=== Prediction examples ===")
for i in range(10):
    print(f"True: {int(ytest[i])+1}  Predicted: {int(pred[i])+1}")
Train samples: 142
Test samples: 36
Feature size: 13
Start learning...
step 0, loss=0.9613
step 200, loss=0.0671
step 400, loss=0.0366
step 600, loss=0.0252
step 800, loss=0.0190
step 1000, loss=0.0151
step 1200, loss=0.0123
step 1400, loss=0.0104
step 1600, loss=0.0089
step 1800, loss=0.0077

=== Test Accuracy ===
Accuracy: 100.00%

=== Prediction examples ===
True: 3  Predicted: 3
True: 3  Predicted: 3
True: 3  Predicted: 3
True: 3  Predicted: 3
True: 3  Predicted: 3
True: 3  Predicted: 3
True: 3  Predicted: 3
True: 3  Predicted: 3
True: 3  Predicted: 3
True: 3  Predicted: 3

Loss Curve¶

I learnt making loss curve using sklearn and made it with help of Mr. Tuchiya.

In [5]:
from sklearn.neural_network import MLPClassifier
from sklearn.preprocessing import StandardScaler
from sklearn import model_selection
import numpy as np
from datetime import datetime as dt


X = df.loc[:,['Color intensity','Hue','Total phenols']]
columns = X.columns
X = X.to_numpy()
print(X.shape)

df_a = df.dropna(subset=['Alcohol'])
df_a['Alcohol'] = df_a['Alcohol'].astype(int)   # 念のため整数化


Y = df_a['Alcohol'].to_numpy()
Y = np.ravel(Y)
print(Y.shape)

scaler = StandardScaler()
X = scaler.fit_transform(X)
#Y = scaler.fit_transform(Y)

X_train,X_test,y_train,y_test = model_selection.train_test_split(X,Y,test_size=0.2)

print(X_train.shape, X_test.shape,y_train.shape,y_test.shape)

model = MLPClassifier()

starttime = dt.now()
model.fit(X_train,y_train)
endtime = dt.now()
print("Predict:",model.score(X_test,y_test)," time:", (endtime.timestamp() - starttime.timestamp()))

plt.title("Loss Curve")
plt.plot(model.loss_curve_)
plt.xlabel("Iteration")
plt.ylabel("Loss")
plt.grid()
(178, 3)
(178,)
(142, 3) (36, 3) (142,) (36,)
Predict: 0.4444444444444444  time: 0.04396510124206543
/Users/lauramt/miniforge3/lib/python3.12/site-packages/sklearn/neural_network/_multilayer_perceptron.py:781: ConvergenceWarning: Stochastic Optimizer: Maximum iterations (200) reached and the optimization hasn't converged yet.
  warnings.warn(
No description has been provided for this image
In [ ]: