Skip to content
This repository has been archived by the owner on Oct 20, 2024. It is now read-only.

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
yiffyrusdev committed May 18, 2020
0 parents commit 12023fb
Show file tree
Hide file tree
Showing 28 changed files with 1,649 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
presentation
Demos
.ipynb_checkpoints
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
anaconda3-2019.10
64 changes: 64 additions & 0 deletions Backend/Loss.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
from typing import Any, Dict, List, Tuple, Callable

import numpy as np

np.seterr(all='raise')


class Loss:
def loss(self, w: Any, x: Any, y: Any, **kwargs: Any) -> Any:
raise RuntimeError("loss() was not defined in class!")


class Linear(Loss):
def loss(self, w: Any, x: Any, y: Any, **kwargs: Any) -> Any:
raise RuntimeError("loss() was not defined in class!")


class Gradient:
def grad(self, w: Any, x: Any, y: Any, **kwargs: Any) -> Any:
raise RuntimeError("grad() was not defined in class!")


class LinearMSE(Linear, Gradient):
"""Mean Squared Error."""

def loss(self,
w: np.matrix,
x: np.matrix,
y: np.matrix,
**kwargs: Any) -> float:
"""
Loss function. Returns float value: MSE.
Positional arguments:
w: np.matrix. Weights of Linear regression.
x: np.matrix. Samples.
y: np.matrix. Real answers.
"""
y_pred = x * w
misses = np.array(y_pred - y)
misses = misses**2
loss = np.sum(misses) / len(y)
return loss

def grad(self,
w: np.matrix,
x: np.matrix,
y: np.matrix,
**kwargs: Any) -> np.matrix:
"""
Gradient vector function for linear regression. Returns grad vector.
Positional arguments:
w: np.matrix. Weights of Linear regression.
x: np.matrix. Samples.
y: np.matrix. Real answers.
"""
gradvec = []
for j, _ in enumerate(w):
gradcoord = np.sum([2 * x[i, j] * (x[i] * w - y[i])
for i in range(x.shape[0])]) / x.shape[0]
gradvec.append(gradcoord)
return np.matrix(gradvec)
117 changes: 117 additions & 0 deletions Backend/Optimization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# -*- coding: utf-8 -*-
from typing import Any, Tuple, Union

import numpy as np

from .Loss import Gradient as LG

np.seterr(all='raise')


class Optimization:
def step(self, w: Any, x: Any, y: Any, **kwargs: Any) -> Any:
raise RuntimeError("step() was not defined in class!")


class Linear(Optimization):
def step(self, w: Any, x: Any, y: Any, **kwargs: Any) -> Tuple[Any, Any]:
raise RuntimeError("step() was not defined in class!")


class Gradient(Linear):
def __init__(self, lossObj: LG, **kwargs: Union[int, float]) -> None:
self._random_weight = kwargs.get("random_weight", 0.001)
self._random_grad = kwargs.get("random_grad", 0)
self._lossObj = lossObj
if not isinstance(lossObj, LG):
raise TypeError("lossObj is not a Gradient loss function")

def loss(self, w: np.matrix, x: np.matrix, y: np.matrix) -> float:
return self._lossObj.loss(w, x, y)

def step(self,
w: np.matrix,
x: np.matrix,
y: np.matrix,
**kwargs: Any) -> Tuple[np.matrix, float]:
max_loss_try = kwargs.get("max_loss_try", 10)
lr = kwargs.get("lr", 0.001)

old_loss = self.loss(w, x, y)
loss = old_loss + 1

while (max_loss_try > 0) and (old_loss < loss):
try_w = self._prep_weights(w)
try_g = self._gradient(try_w, x, y)
try_w = self._upd_weights(try_g, try_w, lr=lr)
loss = self.loss(try_w, x, y)
max_loss_try -= 1
lr /= 2

return try_w, lr

def _gradient(self,
w: np.matrix,
x: np.matrix,
y: np.matrix) -> np.ndarray:
g = self._lossObj.grad(w, x, y).reshape(*w.shape)
return g + np.random.randn(*g.shape) * self._random_grad

def _prep_weights(self, w: np.matrix) -> np.matrix:
return w + np.random.randn(*w.shape) * self._random_weight

def _upd_weights(self,
g: np.ndarray,
w: np.matrix,
lr: float) -> np.matrix:
return w - g * lr


class SGD(Gradient):
def __init__(self, lossObj: LG, **kwargs: Union[float, int]) -> None:
super().__init__(lossObj, **kwargs)
self._batch_size = int(kwargs.get("batch_size", 10))

def step(self,
w: np.matrix,
x: np.matrix,
y: np.matrix,
**kwargs: Any) -> np.matrix:
lr = kwargs.get("lr", 0.001)
w = self._prep_weights(w)
x, y = self._shuffle_xy(x, y)

for b in range(0, x.shape[0], self._batch_size):
x_batch = x[b:b + self._batch_size]
y_batch = y[b:b + self._batch_size]
g = self._gradient(w, x_batch, y_batch)
w = self._upd_weights(g, w, lr=lr)
return w, lr

def _shuffle_xy(self,
x: np.matrix,
y: np.matrix) -> Tuple[np.matrix, np.matrix]:
shuffled_x = np.empty(x.shape, dtype=x.dtype)
shuffled_y = np.empty(y.shape, dtype=y.dtype)
permutation = np.random.permutation(len(x))
for old_index, new_index in enumerate(permutation):
shuffled_x[new_index] = x[old_index]
shuffled_y[new_index] = y[old_index]
return shuffled_x, shuffled_y


class MomentGrad(Gradient):
def __init__(self, lossObj: LG, **kwargs: Any) -> None:
super().__init__(lossObj, **kwargs)
self._prev_coef = float(kwargs.get("prev_coef", 0.5))
print(self._prev_coef)
self._prev_g = 0

def _upd_weights(self,
g: np.ndarray,
w: np.matrix,
**kwargs: Any) -> np.matrix:
lr = kwargs['lr']
delta_w = lr * (self._prev_coef * self._prev_g + g)
self._prev_g = g
return w - delta_w
125 changes: 125 additions & 0 deletions Backend/Regression.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# -*- coding: utf-8 -*-
from typing import Any, Dict, Tuple, Union, List

import numpy as np

from .Optimization import Linear as OL

np.seterr(all='raise')


class Regression:
def fit(self, *args: Any, **kwargs: Any) -> Any:
raise RuntimeError("fit() was not specified!")


class LinearRegression(Regression):
_fitted: bool
_weights: np.matrix

def __init__(self) -> None:
self._fitted = False

def fit(self,
x: np.matrix,
y: np.matrix,
optiObj: OL,
**kwargs: Any) -> Dict[str, list]:
lr = float(kwargs.get("lr", 0.001))
loss_stop = float(kwargs.get("loss_stop", 0.01))
delta_loss_stop = float(kwargs.get("delta_loss_stop", 0.0001))
max_iter = int(kwargs.get("max_iter", 2000))
hot_start = bool(kwargs.get("hot_start", False))

fit_history: Dict[str, List[Union[int, float]]] = {
"i": [],
"loss": [],
"delta_loss": [],
"weights": [],
"lr": []
}

if not isinstance(optiObj, OL):
raise TypeError("optiObj is not a Linear Optimization object")

x, y = self._perpare_xy(x, y)
if not hot_start:
self._weights = np.random.uniform(np.min(x), np.max(x), x.shape[1])
self._weights = np.matrix(self._weights.reshape(x.shape[1], 1))

loss = optiObj.loss(self._weights, x, y)
delta_loss = delta_loss_stop + 1
i = 0
try:
for i in range(max_iter):
if loss <= loss_stop:
break
if delta_loss <= delta_loss_stop and delta_loss > 0:
break
new_lr = self._one_train(x, y, optiObj.step, lr=lr)
new_loss = optiObj.loss(self._weights, x, y)

delta_loss = loss - new_loss
loss = new_loss

fit_history['i'].append(i)
fit_history['loss'].append(loss)
fit_history['delta_loss'].append(delta_loss)
fit_history['weights'].append(self._weights)
fit_history['lr'].append(new_lr)

self._fitted = True
except Exception as e:
raise e
finally:
return fit_history

def _one_train(self,
x: np.matrix,
y: np.matrix,
optiFunc: OL,
**kwargs: float) -> float:
self._weights, lr = optiFunc(self._weights, x, y, **kwargs)
return lr

def _perpare_xy(self,
x: np.matrix,
y: np.matrix) -> Tuple[np.matrix, np.matrix]:
if not (isinstance(x, np.ndarray) or isinstance(x, np.matrix)):
raise TypeError("x is not an np.array/np.matrix type")
if not (isinstance(y, np.ndarray) or isinstance(y, np.matrix)):
raise TypeError("y is not an np.array/np.matrix type")

x, y = np.matrix(x), np.matrix(y)
x = np.hstack((x, np.ones((x.shape[0], 1))))

try:
if x.shape[0] != y.shape[0] or y.shape[1] != 1:
raise ValueError(f"x{x.shape} not compatible with y{y.shape}")
except IndexError:
raise ValueError(f"wrong: x{x.shape}, y{y.shape}: x(m,n), y(m,1)")

return x, y


class LinearRandom(LinearRegression):
def fit(self,
x: np.matrix,
y: np.matrix,
optiObj: OL,
**kwargs: Any) -> Dict[str, list]:
x, y = self._perpare_xy(x, y)
self._weights = np.random.uniform(np.min(x), np.max(x), x.shape[1])
self._weights = np.matrix(self._weights.reshape(x.shape[1], 1))

loss = optiObj.loss(self._weights, x, y)

fit_history = {
"i": [1],
"loss": [loss],
"delta_loss": [0.0],
"weights": [self._weights],
"lr": [0]
}

return fit_history
Binary file added Backend/__pycache__/Loss.cpython-37.pyc
Binary file not shown.
Binary file added Backend/__pycache__/Loss.cpython-38.pyc
Binary file not shown.
Binary file added Backend/__pycache__/Optimization.cpython-37.pyc
Binary file not shown.
Binary file added Backend/__pycache__/Optimization.cpython-38.pyc
Binary file not shown.
Binary file added Backend/__pycache__/Regression.cpython-37.pyc
Binary file not shown.
Binary file added Backend/__pycache__/Regression.cpython-38.pyc
Binary file not shown.
30 changes: 30 additions & 0 deletions Frontend/ExceptionPopup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file './ExceptionPopup.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtWidgets

class Ui_ExceptionPopup(object):
def setupUi(self, ExceptionPopup):
ExceptionPopup.setObjectName("ExceptionPopup")
ExceptionPopup.resize(818, 300)
self.buttonOk = QtWidgets.QPushButton(ExceptionPopup)
self.buttonOk.setGeometry(QtCore.QRect(330, 270, 105, 30))
self.buttonOk.setObjectName("buttonOk")
self.textException = QtWidgets.QTextEdit(ExceptionPopup)
self.textException.setGeometry(QtCore.QRect(0, 10, 821, 251))
self.textException.setReadOnly(True)
self.textException.setObjectName("textException")

self.retranslateUi(ExceptionPopup)
QtCore.QMetaObject.connectSlotsByName(ExceptionPopup)

def retranslateUi(self, ExceptionPopup):
_translate = QtCore.QCoreApplication.translate
ExceptionPopup.setWindowTitle(_translate("ExceptionPopup", "Unhandled Exception"))
self.buttonOk.setText(_translate("ExceptionPopup", "OK"))

45 changes: 45 additions & 0 deletions Frontend/ExceptionPopup.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExceptionPopup</class>
<widget class="QDialog" name="ExceptionPopup">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>818</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Unhandled Exception</string>
</property>
<widget class="QPushButton" name="buttonOk">
<property name="geometry">
<rect>
<x>330</x>
<y>270</y>
<width>105</width>
<height>30</height>
</rect>
</property>
<property name="text">
<string>OK</string>
</property>
</widget>
<widget class="QTextEdit" name="textException">
<property name="geometry">
<rect>
<x>0</x>
<y>10</y>
<width>821</width>
<height>251</height>
</rect>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
Loading

0 comments on commit 12023fb

Please sign in to comment.