import torch
import torch.nn as nn
import numpy as np

from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

import matplotlib.pyplot as plt


class LogisticRegression(nn.Module):

    def __init__(self, n_input_features):
        super(LogisticRegression, self).__init__()
        self.linear = nn.Linear(n_input_features, 1)

    def forward(self, x):
        y_predicted = torch.sigmoid(self.linear(x))
        return y_predicted


def main():
    # 1. Preparing coco
    bc = datasets.load_breast_cancer()
    X, y = bc.data, bc.target

    n_samples, n_features = X.shape

    x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1234)

    # scale features
    sc = StandardScaler()
    x_train = sc.fit_transform(x_train)
    x_test = sc.transform(x_test)

    x_train = torch.from_numpy(x_train.astype(np.float32))
    x_test = torch.from_numpy(x_test.astype(np.float32))
    y_train = torch.from_numpy(y_train.astype(np.float32))
    y_test = torch.from_numpy(y_test.astype(np.float32))

    y_train = y_train.view(y_train.shape[0], 1)
    y_test = y_test.view(y_test.shape[0], 1)

    # 2. Model
    model = LogisticRegression(n_features)

    # 3. Loss and Optimizer
    learning_rate = 0.01
    criterion = nn.BCELoss()
    optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

    # 4. Training Loop
    num_epochs = 100
    for epoch in range(num_epochs):
        # Forward Pass
        y_predicted = model(x_train)
        loss = criterion(y_predicted, y_train)

        # Backward Pass
        loss.backward()

        # Optimizer
        optimizer.step()

        if (epoch + 1) % 10 == 0:
            print(f'epoch: {epoch + 1}, loss = {loss.item():.4f}')

    with torch.no_grad():
        y_predicted = model(x_test)
        y_predicted_cls = y_predicted.round()
        acc = y_predicted_cls.eq(y_test).sum() / float(y_test.shape[0])
        print(f'accuracy = {acc:.4f}')


if __name__ == '__main__':
    main()

import torch
import torch.nn as nn
import numpy as np

from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

import matplotlib.pyplot as plt


class LogisticRegression(nn.Module):

    def __init__(self, n_input_features):
        super(LogisticRegression, self).__init__()
        self.linear = nn.Linear(n_input_features, 1)

    def forward(self, x):
        y_predicted = torch.sigmoid(self.linear(x))
        return y_predicted


def main():
    # 1. Preparing coco
    bc = datasets.load_breast_cancer()
    X, y = bc.data, bc.target

    n_samples, n_features = X.shape

    x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1234)

    # scale features
    sc = StandardScaler()
    x_train = sc.fit_transform(x_train)
    x_test = sc.transform(x_test)

    x_train = torch.from_numpy(x_train.astype(np.float32))
    x_test = torch.from_numpy(x_test.astype(np.float32))
    y_train = torch.from_numpy(y_train.astype(np.float32))
    y_test = torch.from_numpy(y_test.astype(np.float32))

    y_train = y_train.view(y_train.shape[0], 1)
    y_test = y_test.view(y_test.shape[0], 1)

    # 2. Model
    model = LogisticRegression(n_features)

    # 3. Loss and Optimizer
    learning_rate = 0.01
    criterion = nn.BCELoss()
    optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

    # 4. Training Loop
    num_epochs = 100
    for epoch in range(num_epochs):
        # Forward Pass
        y_predicted = model(x_train)
        loss = criterion(y_predicted, y_train)

        # Backward Pass
        loss.backward()

        # Optimizer
        optimizer.step()

        if (epoch + 1) % 10 == 0:
            print(f'epoch: {epoch + 1}, loss = {loss.item():.4f}')

    with torch.no_grad():
        y_predicted = model(x_test)
        y_predicted_cls = y_predicted.round()
        acc = y_predicted_cls.eq(y_test).sum() / float(y_test.shape[0])
        print(f'accuracy = {acc:.4f}')


if __name__ == '__main__':
    main()

# 1. Preparing coco # scale features # 2. Model # 3. Loss and Optimizer # 4. Training Loop # Forward Pass # Backward Pass # Optimizer