├── .gitignore ├── Datasets ├── breast_cancer.csv ├── iris.csv └── student-mat.csv ├── Keras ├── ANN.txt ├── BasicKeras.py ├── KerasIris.py ├── Notes_KerasDeepLearning.txt └── SimpleDNN.py ├── LICENCE ├── Libraries ├── Keras_demo.py ├── Matplotlib_demo.py ├── NumPy_demo.py ├── Pandas_demo.py └── SKLearn_demo.py ├── ML_Algorithms.py ├── Mathematics.ipynb ├── Mathematics ├── Calculus.py ├── LinearAlgebra.ipynb ├── LinearRegression.py └── SigmoidFunction.py ├── Neural-Networks ├── ImageRecognition.py └── text │ ├── analyse_me │ ├── model.h5 │ └── text_recognition.py ├── README.md ├── References ├── arrays.py ├── matrix.py ├── notes.py └── vector.py ├── Single-Layerd-ANN ├── HighLevel_SLNN.ipynb ├── LowLevel_SLNN.ipynb ├── adaline.png └── perceptron.jpg ├── Supervised ├── BreastCancer.ipynb ├── CancerClassification.py ├── Classification.py ├── LinearRegression_Diabetes.ipynb ├── LinearRegression_Grades.ipynb ├── ModelTester.ipynb ├── SVM.py └── Sigmoid.ipynb ├── Unsupervised ├── KMeansExample.ipynb └── unsupervised.py ├── image-1.png ├── image-2.png ├── image.png └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Editors 2 | .vscode/ 3 | .idea/ 4 | 5 | # Vagrant 6 | .vagrant/ 7 | 8 | # Mac/OSX 9 | .DS_Store 10 | 11 | # Windows 12 | Thumbs.db 13 | 14 | # Source for the following rules: https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore 15 | # Byte-compiled / optimized / DLL files 16 | __pycache__/ 17 | *.py[cod] 18 | *$py.class 19 | 20 | # C extensions 21 | *.so 22 | 23 | # Distribution / packaging 24 | .Python 25 | build/ 26 | develop-eggs/ 27 | dist/ 28 | downloads/ 29 | eggs/ 30 | .eggs/ 31 | lib/ 32 | lib64/ 33 | parts/ 34 | sdist/ 35 | var/ 36 | wheels/ 37 | *.egg-info/ 38 | .installed.cfg 39 | *.egg 40 | MANIFEST 41 | 42 | # PyInstaller 43 | # Usually these files are written by a python script from a template 44 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 45 | *.manifest 46 | *.spec 47 | 48 | # Installer logs 49 | pip-log.txt 50 | pip-delete-this-directory.txt 51 | 52 | # Unit test / coverage reports 53 | htmlcov/ 54 | .tox/ 55 | .nox/ 56 | .coverage 57 | .coverage.* 58 | .cache 59 | nosetests.xml 60 | coverage.xml 61 | *.cover 62 | .hypothesis/ 63 | .pytest_cache/ 64 | 65 | # Translations 66 | *.mo 67 | *.pot 68 | 69 | # Django stuff: 70 | *.log 71 | local_settings.py 72 | db.sqlite3 73 | 74 | # Flask stuff: 75 | instance/ 76 | .webassets-cache 77 | 78 | # Scrapy stuff: 79 | .scrapy 80 | 81 | # Sphinx documentation 82 | docs/_build/ 83 | 84 | # PyBuilder 85 | target/ 86 | 87 | # Jupyter Notebook 88 | .ipynb_checkpoints 89 | 90 | # IPython 91 | profile_default/ 92 | ipython_config.py 93 | 94 | # pyenv 95 | .python-version 96 | 97 | # celery beat schedule file 98 | celerybeat-schedule 99 | 100 | # SageMath parsed files 101 | *.sage.py 102 | 103 | # Environments 104 | .env 105 | .venv 106 | env/ 107 | venv/ 108 | ENV/ 109 | env.bak/ 110 | venv.bak/ 111 | 112 | # Spyder project settings 113 | .spyderproject 114 | .spyproject 115 | 116 | # Rope project settings 117 | .ropeproject 118 | 119 | # mkdocs documentation 120 | /site 121 | 122 | # mypy 123 | .mypy_cache/ 124 | .dmypy.json 125 | dmypy.json -------------------------------------------------------------------------------- /Datasets/iris.csv: -------------------------------------------------------------------------------- 1 | sepal_length,sepal_width,petal_length,petal_width,species 2 | 5.1,3.5,1.4,0.2,setosa 3 | 4.9,3.0,1.4,0.2,setosa 4 | 4.7,3.2,1.3,0.2,setosa 5 | 4.6,3.1,1.5,0.2,setosa 6 | 5.0,3.6,1.4,0.2,setosa 7 | 5.4,3.9,1.7,0.4,setosa 8 | 4.6,3.4,1.4,0.3,setosa 9 | 5.0,3.4,1.5,0.2,setosa 10 | 4.4,2.9,1.4,0.2,setosa 11 | 4.9,3.1,1.5,0.1,setosa 12 | 5.4,3.7,1.5,0.2,setosa 13 | 4.8,3.4,1.6,0.2,setosa 14 | 4.8,3.0,1.4,0.1,setosa 15 | 4.3,3.0,1.1,0.1,setosa 16 | 5.8,4.0,1.2,0.2,setosa 17 | 5.7,4.4,1.5,0.4,setosa 18 | 5.4,3.9,1.3,0.4,setosa 19 | 5.1,3.5,1.4,0.3,setosa 20 | 5.7,3.8,1.7,0.3,setosa 21 | 5.1,3.8,1.5,0.3,setosa 22 | 5.4,3.4,1.7,0.2,setosa 23 | 5.1,3.7,1.5,0.4,setosa 24 | 4.6,3.6,1.0,0.2,setosa 25 | 5.1,3.3,1.7,0.5,setosa 26 | 4.8,3.4,1.9,0.2,setosa 27 | 5.0,3.0,1.6,0.2,setosa 28 | 5.0,3.4,1.6,0.4,setosa 29 | 5.2,3.5,1.5,0.2,setosa 30 | 5.2,3.4,1.4,0.2,setosa 31 | 4.7,3.2,1.6,0.2,setosa 32 | 4.8,3.1,1.6,0.2,setosa 33 | 5.4,3.4,1.5,0.4,setosa 34 | 5.2,4.1,1.5,0.1,setosa 35 | 5.5,4.2,1.4,0.2,setosa 36 | 4.9,3.1,1.5,0.1,setosa 37 | 5.0,3.2,1.2,0.2,setosa 38 | 5.5,3.5,1.3,0.2,setosa 39 | 4.9,3.1,1.5,0.1,setosa 40 | 4.4,3.0,1.3,0.2,setosa 41 | 5.1,3.4,1.5,0.2,setosa 42 | 5.0,3.5,1.3,0.3,setosa 43 | 4.5,2.3,1.3,0.3,setosa 44 | 4.4,3.2,1.3,0.2,setosa 45 | 5.0,3.5,1.6,0.6,setosa 46 | 5.1,3.8,1.9,0.4,setosa 47 | 4.8,3.0,1.4,0.3,setosa 48 | 5.1,3.8,1.6,0.2,setosa 49 | 4.6,3.2,1.4,0.2,setosa 50 | 5.3,3.7,1.5,0.2,setosa 51 | 5.0,3.3,1.4,0.2,setosa 52 | 7.0,3.2,4.7,1.4,versicolor 53 | 6.4,3.2,4.5,1.5,versicolor 54 | 6.9,3.1,4.9,1.5,versicolor 55 | 5.5,2.3,4.0,1.3,versicolor 56 | 6.5,2.8,4.6,1.5,versicolor 57 | 5.7,2.8,4.5,1.3,versicolor 58 | 6.3,3.3,4.7,1.6,versicolor 59 | 4.9,2.4,3.3,1.0,versicolor 60 | 6.6,2.9,4.6,1.3,versicolor 61 | 5.2,2.7,3.9,1.4,versicolor 62 | 5.0,2.0,3.5,1.0,versicolor 63 | 5.9,3.0,4.2,1.5,versicolor 64 | 6.0,2.2,4.0,1.0,versicolor 65 | 6.1,2.9,4.7,1.4,versicolor 66 | 5.6,2.9,3.6,1.3,versicolor 67 | 6.7,3.1,4.4,1.4,versicolor 68 | 5.6,3.0,4.5,1.5,versicolor 69 | 5.8,2.7,4.1,1.0,versicolor 70 | 6.2,2.2,4.5,1.5,versicolor 71 | 5.6,2.5,3.9,1.1,versicolor 72 | 5.9,3.2,4.8,1.8,versicolor 73 | 6.1,2.8,4.0,1.3,versicolor 74 | 6.3,2.5,4.9,1.5,versicolor 75 | 6.1,2.8,4.7,1.2,versicolor 76 | 6.4,2.9,4.3,1.3,versicolor 77 | 6.6,3.0,4.4,1.4,versicolor 78 | 6.8,2.8,4.8,1.4,versicolor 79 | 6.7,3.0,5.0,1.7,versicolor 80 | 6.0,2.9,4.5,1.5,versicolor 81 | 5.7,2.6,3.5,1.0,versicolor 82 | 5.5,2.4,3.8,1.1,versicolor 83 | 5.5,2.4,3.7,1.0,versicolor 84 | 5.8,2.7,3.9,1.2,versicolor 85 | 6.0,2.7,5.1,1.6,versicolor 86 | 5.4,3.0,4.5,1.5,versicolor 87 | 6.0,3.4,4.5,1.6,versicolor 88 | 6.7,3.1,4.7,1.5,versicolor 89 | 6.3,2.3,4.4,1.3,versicolor 90 | 5.6,3.0,4.1,1.3,versicolor 91 | 5.5,2.5,4.0,1.3,versicolor 92 | 5.5,2.6,4.4,1.2,versicolor 93 | 6.1,3.0,4.6,1.4,versicolor 94 | 5.8,2.6,4.0,1.2,versicolor 95 | 5.0,2.3,3.3,1.0,versicolor 96 | 5.6,2.7,4.2,1.3,versicolor 97 | 5.7,3.0,4.2,1.2,versicolor 98 | 5.7,2.9,4.2,1.3,versicolor 99 | 6.2,2.9,4.3,1.3,versicolor 100 | 5.1,2.5,3.0,1.1,versicolor 101 | 5.7,2.8,4.1,1.3,versicolor 102 | 6.3,3.3,6.0,2.5,virginica 103 | 5.8,2.7,5.1,1.9,virginica 104 | 7.1,3.0,5.9,2.1,virginica 105 | 6.3,2.9,5.6,1.8,virginica 106 | 6.5,3.0,5.8,2.2,virginica 107 | 7.6,3.0,6.6,2.1,virginica 108 | 4.9,2.5,4.5,1.7,virginica 109 | 7.3,2.9,6.3,1.8,virginica 110 | 6.7,2.5,5.8,1.8,virginica 111 | 7.2,3.6,6.1,2.5,virginica 112 | 6.5,3.2,5.1,2.0,virginica 113 | 6.4,2.7,5.3,1.9,virginica 114 | 6.8,3.0,5.5,2.1,virginica 115 | 5.7,2.5,5.0,2.0,virginica 116 | 5.8,2.8,5.1,2.4,virginica 117 | 6.4,3.2,5.3,2.3,virginica 118 | 6.5,3.0,5.5,1.8,virginica 119 | 7.7,3.8,6.7,2.2,virginica 120 | 7.7,2.6,6.9,2.3,virginica 121 | 6.0,2.2,5.0,1.5,virginica 122 | 6.9,3.2,5.7,2.3,virginica 123 | 5.6,2.8,4.9,2.0,virginica 124 | 7.7,2.8,6.7,2.0,virginica 125 | 6.3,2.7,4.9,1.8,virginica 126 | 6.7,3.3,5.7,2.1,virginica 127 | 7.2,3.2,6.0,1.8,virginica 128 | 6.2,2.8,4.8,1.8,virginica 129 | 6.1,3.0,4.9,1.8,virginica 130 | 6.4,2.8,5.6,2.1,virginica 131 | 7.2,3.0,5.8,1.6,virginica 132 | 7.4,2.8,6.1,1.9,virginica 133 | 7.9,3.8,6.4,2.0,virginica 134 | 6.4,2.8,5.6,2.2,virginica 135 | 6.3,2.8,5.1,1.5,virginica 136 | 6.1,2.6,5.6,1.4,virginica 137 | 7.7,3.0,6.1,2.3,virginica 138 | 6.3,3.4,5.6,2.4,virginica 139 | 6.4,3.1,5.5,1.8,virginica 140 | 6.0,3.0,4.8,1.8,virginica 141 | 6.9,3.1,5.4,2.1,virginica 142 | 6.7,3.1,5.6,2.4,virginica 143 | 6.9,3.1,5.1,2.3,virginica 144 | 5.8,2.7,5.1,1.9,virginica 145 | 6.8,3.2,5.9,2.3,virginica 146 | 6.7,3.3,5.7,2.5,virginica 147 | 6.7,3.0,5.2,2.3,virginica 148 | 6.3,2.5,5.0,1.9,virginica 149 | 6.5,3.0,5.2,2.0,virginica 150 | 6.2,3.4,5.4,2.3,virginica 151 | 5.9,3.0,5.1,1.8,virginica 152 | -------------------------------------------------------------------------------- /Keras/ANN.txt: -------------------------------------------------------------------------------- 1 | Input Data: 2 | - Data the model is trained upon, images, values, etc.. 3 | - Data is interpreted as a tensor (n-dimensional matrix) 4 | - For DL experiments, it is common practice to use one training sample for each column. 5 | - It is good practice to normalize, standardize or scale the input values before training. 6 | - Normalize: Converts every input values into a range of 0 to 1. 7 | - Standardize: Convert every input value into a range where the mean is 0 and the standard deviation is 1. 8 | - Scale: Only use part of the input data. 9 | 10 | Neuron: 11 | - In overall a function that takes input and converts it into an output. 12 | - The neuron receives one or more inputs from neurons in the previous layer. 13 | - The neurons in the first hidden layer receive the data from the input data stream. 14 | - Mimic the biological neuron, fireing or not fireing based on a higher-influence input. 15 | 16 | Activation Function: 17 | - A function that operates on the sum of input multiplied by the corresponding weights. 18 | - It applies a function to the input and returns the output value 19 | - Responds with an appropriate value based on the input: 20 | - Returns higher output when higher-influence value is input and vise versa. 21 | - Higher-Influence -> Acvivate, else Deactivate 22 | - Denoted as: f(z) 23 | ! Constant with a derivative of 0: 24 | - Network will not be able to learn because the backpropagation uses the derivative to adjust its weights. 25 | - If changing this value to 0, the network won't update / learn. 26 | - An example of this is a linear function (basically no activation) 27 | Functions: 28 | - To avoid the "constant with a derivative of 0" issue, always choose a non-linear activation function for the hidden layers. 29 | Sigmoid: 30 | - Defined as: 1 / (1 + e^-z) 31 | - Renders output between 0 and 1. 32 | - A non-linear(s-shaped) function. 33 | - Improves learning process well because it closely resembles the higher-influence -> higher output principle. 34 | - Python: 35 | import keras.activations.sigmoid 36 | sigmoid(x) 37 | 38 | ReLU (Rectified Linear Unit): 39 | - Defined as: max(0,z); 40 | - If output is positive, output the value, else output 0. 41 | - Renders output between 0 and 1. 42 | - A valid non-linear function. 43 | - By deactivating the neuron with any negative input, it reduces the computations needed dureing the training phase. 44 | - Python: 45 | keras.activations.relu(x, alpha=0.0, max_value=None) 46 | 47 | Leaky ReLU: 48 | 49 | Model: 50 | 51 | Layers: 52 | Core Layers: 53 | Dense Layer: 54 | Dropout Layer: 55 | Other Layers: 56 | 57 | Loss Function: 58 | Binary cross-entropy: 59 | Categorical cross-entropy: 60 | 61 | Optimizers: 62 | Stochastic Gradient Descent (SGD): 63 | Adam: 64 | Other Optimizers: 65 | 66 | Metrics: 67 | Model Configuration: 68 | Model Training: 69 | Model Evaluation: -------------------------------------------------------------------------------- /Keras/BasicKeras.py: -------------------------------------------------------------------------------- 1 | from keras.models import Sequential 2 | from keras.layers import Dense 3 | import numpy as np 4 | 5 | np.random.seed(2018) # Setting seed for reproducibility 6 | 7 | """ GETTING THE DATA READY """ 8 | train_data = np.random.random((1000, 3)) # Random dummy-train data for 1000 students 9 | test_data = np.random.random((500, 3)) # Random dummy-test data for 500 10 | 11 | labels = np.random.randint(2, size=(1000, 1)) # Dummy results for 1000 students (pass or fail) 12 | 13 | """ DEFINING MODEL STRUCTURE """ 14 | model = Sequential() 15 | # Dense(, input_dim=, ) 16 | model.add(Dense(5, input_dim=3, activation='relu')) 17 | model.add(Dense(4, activation='relu')) 18 | model.add(Dense(1, activation='sigmoid')) 19 | model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) 20 | 21 | """ TRAINING THE MODEL AND MAKING PREDICTIONS """ 22 | model.fit(train_data, labels, epochs=10, batch_size=32) # Train model and predict 23 | predictions = model.predict(test_data) # Make predictions from the trained model 24 | -------------------------------------------------------------------------------- /Keras/KerasIris.py: -------------------------------------------------------------------------------- 1 | from keras.models import Sequential 2 | from keras.layers import Dense 3 | from sklearn.datasets import load_iris 4 | import numpy as np 5 | 6 | np.random.seed(2018) # Setting seed for reproducibility 7 | iris = load_iris() 8 | indices = np.random.permutation(len(iris.data)) 9 | test_samples = 12 10 | 11 | train_data = iris.data[indices[:-test_samples]] 12 | test_data = iris.data[indices[-test_samples:]] 13 | labels = iris.target[indices[:-test_samples]] 14 | 15 | model = Sequential() 16 | model.add(Dense(5, input_dim=4, activation='relu')) 17 | model.add(Dense(10, activation='relu')) 18 | model.add(Dense(3, activation='relu')) 19 | model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) 20 | 21 | model.fit(train_data, labels, epochs=10, batch_size=32) 22 | predictions = model.predict(test_data) -------------------------------------------------------------------------------- /Keras/Notes_KerasDeepLearning.txt: -------------------------------------------------------------------------------- 1 | ===============[ DEEP LEARNING ]=============== 2 | - Buzzwords: 3 | - Machine Learning: 4 | - A subfield in AI where intelligence is induced without explicit programming. 5 | - Can predict whether a student will pass or fail a test by learning from historical test results and student attributes. 6 | - The system is not encoded with a comprehensive list of all possible rules that can decide whether a student will pass or fail. 7 | - The system learns on its own based on the patterns in it learned from the historical data. 8 | - Works very well for a variety of problems, but fails to excel in some specific cases that seem very easy for humans (e.g classifications of images, sounds) 9 | - Performs poorly with image and other unstructured data types. 10 | - ML would not be able to improve performance with increased training data after a certain threshold. 11 | - Deep Learning: 12 | - A field within ML where intelligence is induced into systems without explicit programming using algorithms that have been inspired by the biological functioning of the human brain. 13 | - We can leverage DL for all ML tasks and expect better performance, provided there was surplus data availability. 14 | - DL became a ubiquitous field to solve predictive problems rather than just confined to areas of computer vision, speech and so on. 15 | - Today we can leverage DL for almost all use cases that were earlier solved using ML and expect to outperform our previous achievements, provided that there is a surplus of data. 16 | - DL is able to leverage the surplus data more effectively for improved performance. 17 | 18 | - Decomposing a DL Model: 19 | - In its most basic form, DL models are designed using neural netowrk architecture. 20 | - A neural network is a hierarchical organization of neurons with connections to other neurons. 21 | - These neurons pass a message or signal to other neurons based on the received input and form a complex network that learns with some feedback mechanism. 22 | - The input data is consumed by the neurons in the first hidden layer, which then provide an output to the next layer and so on, eventually resulting in the final output. 23 | - Each layer can have one or many neurons, and each of them will compute a small function (e.g. activation function). 24 | - The connection between two neurons of successive layers would have an associated weight. 25 | - The weight defines the influence of the input to the output for the next neuron and eventually for the overall final output. 26 | - In a neural network, the initial weights would all be random during the model training, but these weights are updated iteratively to learn to predict a correct output. 27 | - Decomposing the network we can define few logical building blocks like neuron, layer, weight, input, output, an activation function inside the neuron to compute a learning process, and so on. 28 | - Structure of a neural network example: 29 | 1. The input is consumed by neurons in the first layer and an activation function is calculated within each neuron. 30 | 2. Based on a simple rule, it forwards an output to the next neuron. 31 | 2a. Similiar to the deviations learned by the human brain. 32 | 3. The larger the output of a neuron, the larger the significance of that input dimension will be. 33 | 4. These dimensions are then combined in the next layer to form additional new dimensions, which we probably cant make sense of. 34 | 5. The process, when multiplied several times, develops a complex network with several connections. 35 | - Learning process of a neural network example: 36 | 1. When we provide the input data to the defined structure, the end output would be a prediction, which could be either correct or incorrect. 37 | 2. Based on the output, if we provide a feedback to the network to adapt better by using some means to make a better prediction, the system learns by updating the weight for the connections. 38 | 3. To achieve the process of providing feedback and defining the next step to make changs in the corect way, we use a beautiful mathematical algorithm called "Backpropagation". 39 | 4. Iterating the process several times step by step, with more and more date, helps the network update the weights appropriately to create a system where it can make a decision for predicting output based on the rules it has created for itself through the weights and connections. 40 | - Building blocks in a DL model: 41 | - Neurons, Activation Functions, Optimization Algorithms, Data Augmentation Tools, and so on.. 42 | 43 | * Popular DL Frameworks: 44 | - Low-Level DL Frameworks: 45 | - Given the level of abstraction a framework provides, we can classify it as a low-level or high-level DL framework. 46 | - While this is by no means industry-recognized terminology, we can use the segregation for a more intuitive understanding of the frameworks. 47 | - Can be defined as the first level of abstraction of DL models. 48 | - You would have to write fairly long codes and scripts to get your DL model ready (Although much less so than using just Python or C++). 49 | - The advantage of using the first-level abstraction is the flexibility it provides in designing a model. 50 | - Theano: 51 | - One of the first DL libraries to gain popularity. 52 | - Open source Python library 53 | - Torch: 54 | - Another popular ML and DL framework based on the Lua programming language. 55 | - Improved by Facebook with a set of extension modules as open source software. 56 | - PyTorch: 57 | - Open source ML and DL library for Python. 58 | - Developed by the Facebook AI research team. 59 | - More popular than Torch, since basic Python skills can get you started developing DL models. 60 | - PyTorch is far easier and transparrent to use for DL development versus Torch. 61 | - MxNet: 62 | - Pronounced "Mix-Net" and stands for both "Mix" and "Maximize". 63 | - The idea was simplified to combine declarative and imperative programming together (mix) to maximize efficiency and productivity. 64 | - It supports the use of multiple GPUs and is widely supported by major cloud providers like AWS and Azure. 65 | - TensorFlow: 66 | - Undoubtedly one of the most popular and widely used DL frameworks in the DL fraternity. 67 | - It was developed and open sourced by Google and supports development across CPUs and GPUs, and mobile & edge devices as well. 68 | - Aditional Frameworks: 69 | - Caffe, Microsoft CNTK, Chainer, PaddlePaddle, and many more! 70 | 71 | - high-Level DL Frameworks: 72 | - To simplify the process of DL models, we have frameworks that work on the seond level of abstraction. 73 | - That is, rather than using the previously mentioned frameworks directly, we can use a new framework on top of an existing framework and thereby simplify DL model development further. 74 | - The most popular high-level DL framework that provides a second level abstraction to Dl model development is Keras. 75 | - Other frameworks like Gluon, Lasagne, and so on are also available, but Keras has been the most widely adopted one. 76 | - Note: 77 | - Gluon works on top of MxNet. 78 | - Lasagne works on top of Theano. 79 | - Keras works on top of TensorFlow, Theano, MxNet & Microsoft CNTK. 80 | - Keras: 81 | - A high-level neural network API written in Python and can help you in developing a fully functional DL model with less than 15 mines of code. 82 | - Since it is written in Python, it has a larger community of users and supporters and is extremely easy to get started with. 83 | - The simplicity of Keras is that it helps users quickly develop DL models and provides a ton of flexibility while still being a high-level API. 84 | - This really makes Keras a special framework to work with. Moreover, given that it supports several other frameworks as a back end, it adds the flexibility to leverage a different low-level API for a different use case if required. 85 | - By far the most widely adopted usage of Keras is with TensorFlow as backend (i.e., Keras as a high-level DL API and TensorFlow as its low-level API back end). 86 | - In a nutshell, the code you write in Keras gets converted to TensorFlow, which then runs on a compute instance. 87 | 88 | - Logical Components: 89 | - Input Data: 90 | - Input data for a DL algorithm can be of a variety of types. 91 | - Tensor: 92 | - An n-dimensional matrix. 93 | - Data of any form is finally represented as a homogeneous numeric matrix. 94 | - Example; a 2-dimensional tensor: 95 | - Each column represents one training sample. 96 | - The entire matrix will be x samples. 97 | * 2-dimensional tensor (m * n): 98 | |_1_|_5_|_3_|_1_|_1_|-\ 99 | |_2_|_4_|_5_|_1_|_2_| | 100 | 1 training sample ->|_3_|_4_|_6_|_8_|_9_| | n rows 101 | |_4_|_5_|_5_|_6_|_7_| | 102 | |_6_|_9_|_1_|_6_|_9_|-/ 103 | \ / 104 | ---- m columns ---- 105 | 106 | - The training samples can also be represented reverse (i.e, each row could be one traing sample) 107 | - In DL experiments, it is common notation to use one training sample in a column. Thus, m columns would denote m samples. 108 | - Image Data: 109 | - A single image is stored in data such as a 3-dimensional tensor where dimensions define the pixel values on a 2D plane and a third dimension defines the values for RGB color channels. 110 | - Multiple images gets transformed into a 4-dimension tensor where the 4'th dimension will stack a 3D tensor image as a training sample. 111 | - Example: 112 | - 100 images with a 512 x 512-pixel resolution, they will be represented as a 4D tensor with shape 512 x 512 x 3 x 100. 113 | - It is a good practice to normalize, standardize, or scale the input values before training. 114 | - Normalizing the values will bring all values in the input tensor into a 0-1 range, and standardization will bring the values into a range where the mean is 0 and the standard deviation is 1. 115 | - This helps to reduce computation, as the learning improves by a great margin and so does performance, as the activation functions behave more appropriately. 116 | 117 | - Neuron: 118 | - The core of a DNN, the neurons perform computations for an output. 119 | - The neurons receives one or more inputs from the neurons in the previous layer. 120 | - If the neurons are in the first hidden layer, they will receive the data from the input data stream. 121 | - To map the functionality in a mathematical neuron, we need to have a function that operates on the sum of input multiplied by the corresponding weights f(z) and responds with an appropriate value based on the input. 122 | - If a higher-influence input is received, the output should be higher, and vice versa. 123 | - It is in a way analogous to the activation signal (i.e., higher influence -> then activate, otherwise deactivate). 124 | - The function that works on the computed input data is called the activation function. 125 | 126 | - Activation Function: 127 | - A function that takes the combined input z, applies a function to it, and passes the output value, thus trying to mimic the activate/deactivate function. 128 | - The activation function therefore determines the state of a neuron by computing the activation function on the combined input. 129 | - By computing the the output through an activation function, we avoid: 130 | - The range of the output value would be -infinity to +infinity, with no clear way to define a threshold. 131 | - The network won't really learn: 132 | - Calculus: 133 | - Derivatives: 134 | - E.g., if the activation function is a linear function (basically no activation), the derivative of that function becomes 0; this becomes a big issue because training with the backpropagation algorithm helps give feedback to the network about wrong classifications and thereby helps a neuron to adjust its weights by using a derivative of the function. 135 | - If that becomes 0, the network loses out on this learning ability. 136 | - The output of just one layer would be similiar to having n layers. 137 | - To keep things simple, we would always need a nonlinear activation function (at least in all hidden layers) to get the network to learn properly. 138 | 139 | - Sigmoid Activation Function: 140 | - f(z) = 1 / (1+e^-z) 141 | - Renders output between 0 and 1. 142 | - The nonlinear output of a sigmoid function improves the learning process very well, as it closely resembles the following principals: 143 | - Lower influence = low output 144 | - Higher influence = high output 145 | - Confines the output between the 0 and 1 range. 146 | 147 | - ReLU Activation Function: 148 | - f(z) = max(0,z) 149 | - If the output is positive it would output the same value, otherwise it would output 0. 150 | - A valid nonlinear function. 151 | - Works really well as an activation function. 152 | - Improves the performance. 153 | - Significantly reduce the number of computations during the training phase. 154 | - This is a direct result of the 0 value in the output when z is negative, thereby deactivating the neuron. 155 | - Because of the horizontal line with 0 as the output, we face serious issues sometimes, for instance: 156 | - If the horizontal line is a constant with a derivative of 0, it may become a bottleneck during training, as the weights will not easily get updated. 157 | - Leaky ReLU: 158 | - To circumvent the horizontal line becoming a constant with a derivative of 0. 159 | - A negative value outputs a slightly slanting line instead of a horizontal line. 160 | - This helps in updating the weights through backpropagation effectively. 161 | - f(z) = z; when z > 0 162 | - f(z) = ~z; when z < 0 and where ~ is a parameter that is defined as a small constant, say 0.005 163 | - python > keras.layers.LeakyReLU(X, alpha=0.0, max_value=None) 164 | - We can directly use the activation function by setting the value of alpha with a small constant. 165 | 166 | - A few other activation functions: 167 | - tanh (hyperbolic tan activation) 168 | - swish activation 169 | - elu (exponential linear unit) 170 | - selu (scaled elu) 171 | ... 172 | 173 | - Model: 174 | - The overall structure of a DNN is developed using the model object in Keras. 175 | - This provides a simple way to create a stack of layers by adding new layers one after the other. 176 | - The sequential model is the easiest way to define a model, which allows easy creation of a linear stack of layers. 177 | - Example (Sequential model with 1 layer followed by an activation): 178 | - The layer have 10 neurons and reveive input from 15 neurons and be activated with the ReLU activation function. 179 | from keras.model import Sequential 180 | from keras.layers import Dense, Activation 181 | 182 | model = Sequential() 183 | model.add(Dense(10, input_dim=15)) 184 | model.add(Activation('relu)) 185 | 186 | 187 | - Layers: 188 | - A layer in a DNN is defined as a group of neurons or a logically separated group in a hierarchical network structure. 189 | - As DL became more and more popular, there were several experiments conducted with network architectures to improve performance for a variety of use cases. 190 | - The use cases centered around regular supervised algorithms like classification and regression, computer vision experiments, extending DL for natural language processing and understanding, speech recognition and combinations of different domains. 191 | - To simplify the model development process, Keras provides us with several types of layers and verious means to connect them. 192 | - Core Layers: 193 | - There are a few important layers that we will be using in mose use cases. 194 | - Dense Layer: 195 | - A dense layer is a regular DNN layer that connects every neuron in the defined leyer to every neuron in the previous layer, for instance: 196 | - If layer 1 has 5 neurons and layer 2 (dense layer) has 3 neurons, the total number of connections between layer 1 and 2 would be 15 (5*3) 197 | - Because it accommodates every possible connection between the layers, it is called a dense layer. 198 | - Keras Dense Layer default parameters: 199 | - keras.layers.Dense(units, activation=None, use_bias=True, 200 | kernel_initializer='glorot_uniform', 201 | bias_initializer='zeros', 202 | kernel_regularizer=None, 203 | bias_regularizer=None, 204 | activity_regularizer=None, 205 | kernel_constraint=None, 206 | bias_constraint=None) 207 | - It offers a lot of customization for any given layer. 208 | - Most often, we just use parameters like units and activation. 209 | - These additional parameters become important when we are working in specialized use cases where the importance of using specific types of constraints and initializers for a given layer is paramount. 210 | - We also need to define the input shape for the Keras layer. 211 | - The input shape needs to be defined for only the first layer. 212 | - Subsequent layers just need the number of neurons defined. 213 | - input_dim: define how many dimensions the input has, for instance: 214 | - If we hace a table with 10 features and 1000 samples, we need to provide input_dim as 10 for the layer to understand the shape of input data. 215 | - Example: 216 | - A network with one hidden layer and the output layer for simple binary classifications. 217 | - Layer 1 has 5 neurons and expects an input with 10 features; therefore, input_dim=10. 218 | - The final layer is the output, which has one neuron. 219 | model = Sequential() 220 | model.add(Dense(5, input_dim=10, activation='sigmoid')) 221 | model.add(Dense(1, activation='sigmoid')) 222 | - Dropout Layer: 223 | - Other Important Layers: 224 | -------------------------------------------------------------------------------- /Keras/SimpleDNN.py: -------------------------------------------------------------------------------- 1 | from keras.models import Sequential 2 | from keras.layers import Dense, Activation 3 | 4 | # Building a DNN with two hidden layers 5 | model = Sequential() 6 | model.add(Dense(32, input_dim=10, activation='relu')) 7 | model.add(Dense(16, activation='relu')) 8 | model.add(Dense(1, activation='sigmoid')) 9 | 10 | model.compile(optimizer='Adam', loss='binary_crossentropy', metrics=['accuracy']) -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. -------------------------------------------------------------------------------- /Libraries/Keras_demo.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytesenseidk/Machine-Learning/57386bce7e3bee8cac5bf25357552b5ce5edddb1/Libraries/Keras_demo.py -------------------------------------------------------------------------------- /Libraries/Matplotlib_demo.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytesenseidk/Machine-Learning/57386bce7e3bee8cac5bf25357552b5ce5edddb1/Libraries/Matplotlib_demo.py -------------------------------------------------------------------------------- /Libraries/NumPy_demo.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytesenseidk/Machine-Learning/57386bce7e3bee8cac5bf25357552b5ce5edddb1/Libraries/NumPy_demo.py -------------------------------------------------------------------------------- /Libraries/Pandas_demo.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytesenseidk/Machine-Learning/57386bce7e3bee8cac5bf25357552b5ce5edddb1/Libraries/Pandas_demo.py -------------------------------------------------------------------------------- /Libraries/SKLearn_demo.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytesenseidk/Machine-Learning/57386bce7e3bee8cac5bf25357552b5ce5edddb1/Libraries/SKLearn_demo.py -------------------------------------------------------------------------------- /ML_Algorithms.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | from matplotlib.colors import ListedColormap 4 | from sklearn.model_selection import train_test_split 5 | from sklearn.preprocessing import StandardScaler 6 | from sklearn.datasets import make_moons, make_circles, make_classification 7 | from sklearn.neural_network import MLPClassifier 8 | from sklearn.neighbors import KNeighborsClassifier 9 | from sklearn.svm import SVC 10 | from sklearn.gaussian_process import GaussianProcessClassifier 11 | from sklearn.gaussian_process.kernels import RBF 12 | from sklearn.tree import DecisionTreeClassifier 13 | from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier 14 | from sklearn.naive_bayes import GaussianNB 15 | from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis 16 | 17 | h = .02 # step size in the mesh 18 | 19 | names = ["Nearest Neighbors", "Linear SVM", "RBF SVM", "Gaussian Process", 20 | "Decision Tree", "Random Forest", "Neural Net", "AdaBoost", 21 | "Naive Bayes", "QDA"] 22 | 23 | classifiers = [ 24 | KNeighborsClassifier(3), 25 | SVC(kernel="linear", C=0.025), 26 | SVC(gamma=2, C=1), 27 | GaussianProcessClassifier(1.0 * RBF(1.0)), 28 | DecisionTreeClassifier(max_depth=5), 29 | RandomForestClassifier(max_depth=5, n_estimators=10, max_features=1), 30 | MLPClassifier(alpha=1, max_iter=1000), 31 | AdaBoostClassifier(), 32 | GaussianNB(), 33 | QuadraticDiscriminantAnalysis()] 34 | 35 | X, y = make_classification(n_features=2, n_redundant=0, n_informative=2, 36 | random_state=1, n_clusters_per_class=1) 37 | rng = np.random.RandomState(2) 38 | X += 2 * rng.uniform(size=X.shape) 39 | linearly_separable = (X, y) 40 | 41 | datasets = [make_moons(noise=0.3, random_state=0), 42 | make_circles(noise=0.2, factor=0.5, random_state=1), 43 | linearly_separable] 44 | 45 | figure = plt.figure(figsize=(27, 9)) 46 | i = 1 47 | 48 | # iterate over datasets 49 | for ds_cnt, ds in enumerate(datasets): 50 | # preprocess dataset, split into training and test part 51 | X, y = ds 52 | X = StandardScaler().fit_transform(X) 53 | X_train, X_test, y_train, y_test = \ 54 | train_test_split(X, y, test_size=.4, random_state=42) 55 | 56 | x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5 57 | y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5 58 | xx, yy = np.meshgrid(np.arange(x_min, x_max, h), 59 | np.arange(y_min, y_max, h)) 60 | 61 | # just plot the dataset first 62 | cm = plt.cm.RdBu 63 | cm_bright = ListedColormap(['#FF0000', '#0000FF']) 64 | ax = plt.subplot(len(datasets), len(classifiers) + 1, i) 65 | if ds_cnt == 0: 66 | ax.set_title("Input data") 67 | # Plot the training points 68 | ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright, 69 | edgecolors='k') 70 | # Plot the testing points 71 | ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, alpha=0.6, 72 | edgecolors='k') 73 | ax.set_xlim(xx.min(), xx.max()) 74 | ax.set_ylim(yy.min(), yy.max()) 75 | ax.set_xticks(()) 76 | ax.set_yticks(()) 77 | i += 1 78 | 79 | # iterate over classifiers 80 | for name, clf in zip(names, classifiers): 81 | ax = plt.subplot(len(datasets), len(classifiers) + 1, i) 82 | clf.fit(X_train, y_train) 83 | score = clf.score(X_test, y_test) 84 | # Plot the decision boundary. For that, we will assign a color to each 85 | # point in the mesh [x_min, x_max]x[y_min, y_max]. 86 | if hasattr(clf, "decision_function"): 87 | Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()]) 88 | else: 89 | Z = clf.predict_proba(np.c_[xx.ravel(), yy.ravel()])[:, 1] 90 | # Put the result into a color plot 91 | Z = Z.reshape(xx.shape) 92 | ax.contourf(xx, yy, Z, cmap=cm, alpha=.8) 93 | # Plot the training points 94 | ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright, 95 | edgecolors='k') 96 | # Plot the testing points 97 | ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, 98 | edgecolors='k', alpha=0.6) 99 | ax.set_xlim(xx.min(), xx.max()) 100 | ax.set_ylim(yy.min(), yy.max()) 101 | ax.set_xticks(()) 102 | ax.set_yticks(()) 103 | if ds_cnt == 0: 104 | ax.set_title(name) 105 | ax.text(xx.max() - .3, yy.min() + .3, ('%.2f' % score).lstrip('0'), 106 | size=15, horizontalalignment='right') 107 | i += 1 108 | 109 | plt.tight_layout() 110 | plt.show() 111 | 112 | -------------------------------------------------------------------------------- /Mathematics.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Systems of linear equation equations\n", 8 | "1. Systems of linear equations play a central part of linear algebra.\n", 9 | "2. Many problems can be formulated as systems of linear equations.\n", 10 | "\n", 11 | "### Symbols and meaning:\n", 12 | "- Scalars (lowercase): $\\quad a, b, c, a\\beta$\n", 13 | "- Vectors (bold): $\\quad \\bold{x, y, z}$\n", 14 | "- Matrices (bold uppercase): $\\quad \\bold{A, B, C}$\n", 15 | "- Transpose of vector and matrix: $\\quad x^T, \\bold{A}^T$\n", 16 | "- Inverse of a matrix: $\\quad A^{-1}$\n", 17 | "- Inner product of x and y: $\\quad \\langle x, y \\rangle$\n", 18 | "- Dot product of x and y: $\\quad x^Ty$\n", 19 | "- Ordered tuple: $\\quad B = (b_1, b_2, b_3)$\n", 20 | "- Horizonally stacked matrix of vectors: $\\quad \\bold{B = [b_1, b_2, b_3]}$\n", 21 | "- Unordered set of vectors: $\\quad \\textit{B = \\{1, 2, 3\\}}$\n", 22 | "\n", 23 | "### Example 1:\n", 24 | "- Products (vector): $N_1,...,N_n$\n", 25 | "- Resources (vector): $R_1,...,R_m$\n", 26 | "- Product (unit): $N_j$\n", 27 | "- Resource (unit): $R_i$\n", 28 | "- Units (amount): $a_{ij}$\n", 29 | "- Units of product (amount): $x_j$\n", 30 | "- Total units (amount): $b_i$\n", 31 | "\n", 32 | "\n", 33 | "1. A company produces ($N_1,...,N_n$) products for which ($R_1,...,R_m$) resources are required.\n", 34 | "2. To produce a unit of product ($N_j$), it requires ($a_{ij}$) units of resource ($R_i$).\n", 35 | " - $i = 1,...,m$\n", 36 | " - $j = 1,...,n$\n", 37 | "3. The object is to find an optimal production plan:\n", 38 | " - A plan of how many units ($x_j$) of product ($N_j$) should be produced if a total of ($b_i$) units of resource ($R_i$) are available with ideally no resources are left over.\n", 39 | "4. To produce ($x_1,...,x_n$) units of the corresponding products, we need a total of ($a_{i1}x_1 + ... + a_{in}x_n$) units of resouces ($R_i$).\n", 40 | "5. An optimal production plan $(x_1,...,x_m)\\in \\Reals{^n}$, has to satisfy the following system of equations:\n", 41 | " - $a_{11}x_1 + ... + a_{1n}x_n = b_1$" 42 | ] 43 | } 44 | ], 45 | "metadata": { 46 | "language_info": { 47 | "name": "python" 48 | }, 49 | "orig_nbformat": 4 50 | }, 51 | "nbformat": 4, 52 | "nbformat_minor": 2 53 | } 54 | -------------------------------------------------------------------------------- /Mathematics/Calculus.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytesenseidk/Machine-Learning/57386bce7e3bee8cac5bf25357552b5ce5edddb1/Mathematics/Calculus.py -------------------------------------------------------------------------------- /Mathematics/LinearAlgebra.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Vectors\n" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": {}, 14 | "outputs": [ 15 | { 16 | "data": { 17 | "text/plain": [ 18 | "[]" 19 | ] 20 | }, 21 | "execution_count": 1, 22 | "metadata": {}, 23 | "output_type": "execute_result" 24 | }, 25 | { 26 | "data": { 27 | "image/png": "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qwCeQWjgeqFQSPv27ZMkHTp0SCtXrlRqaqqzSwEewqvO4Hrl5eW64447FA6HdeTIEd18880aNWqU02sBnuHK0ITDYX3//fcKh8NndTl79+5V69atm/zn4uLi1K5dO/l8vrOaj+aRkZGhDRs2OL0G4FmuC83hw4e1du1fFBe3U/FneXR79+7Tvn0dmvznampshcNddMUV151RqADATVwXmq++2qguXcqVnt7jrC9r9+5WSkxMPMM9yrR58981YMAVZ70HAMQy170Y4ODBverSpZ3Ta6hz53Y6dGiv02sAgONcF5poUfud57bTawCA41wdmpKSnUpIuEmBwJQGz/fZZ1vk8/1Eb7yx5rSXOWbMk7r44nvUr99kjRs3T9XVNZKk//7vv+nCC3+uUaMeaZbdAcAtXB0aSerTp6uKiuad8vRwOKz7739Vw4df0qjLGzPman311bP6/PP5OnSoSi+/vFySdMstP9bLL/+yWXYGADdx3YsBmmr+/D/rxhuv0GefbWnU+a+7bmDd55dd1lelpbtNrQZEncrKShUVrVFFxQ5jM/bu3avzzjvvlKcnJJyn/v2vVPv27Y3tgObl6dCUle3W4sUfa9Wq3zQ6NMdUV9dowYLVmjfvLkPbAdFn3bpl6tFjl/z+jsbeAbv21Z71f1uAbdvavXunPvnkHQ0ZcrNatmxpZAc0L0+HZurUlzR37h1n9I2VkyY9r8GD0/XjH6cb2AyIPocPH9bhw+W66KKz/9aBhrRu3UKtW586ID16tNK2bUFVVFSc8bcfILJc/xzN8Z555l0FAlMUCExRMLhb69d/o5/97AmlpEzQG2+s1aRJz+vttz8+7eU8/PBChUL/1lNPjY/A1kB0sG1bPt+J92JKS7/T9df/RhddNFF9+vxcU6a8pKqq6pP+bDC4Wzfd9H9PO+O66x7Wv/998LTn8/mkI0eONH55OMpTofnFL0aqqGieiormKSkpUVu3vqySktqPm266Qs8+e7d+8pPan7p4zTUPqrz85O+Defnl5XrvvQ1auPBexcV56uoDTmDbtm64YY5+8pNB2rLlBf3jH8/p++8P6YEHCk44X01NWElJiXrjjRmnvcylS2epffs2plaGQzz90NmpHDlyRN98U64OHc456bS7735WyclddPnltT+75IYbLtdDD/0s0isCjlu1qlitW7fQnXcOlST5fD79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", 28 | "text/plain": [ 29 | "
" 30 | ] 31 | }, 32 | "metadata": { 33 | "needs_background": "light" 34 | }, 35 | "output_type": "display_data" 36 | } 37 | ], 38 | "source": [ 39 | "import numpy as np\n", 40 | "import matplotlib.pyplot as plt\n", 41 | "\n", 42 | "# Points on coordinatesystem\n", 43 | "origin = [0, 0] # Center\n", 44 | "color = \"red\"\n", 45 | "vector_xy, vector_xytext = (0, 0), (-4, 2)\n", 46 | "\n", 47 | "# Set length of axes and the space between tick labels\n", 48 | "x_min, x_max, y_min, y_max = -5, 5, -5, 5\n", 49 | "ticks_freq = 1\n", 50 | "\n", 51 | "# Plot examples\n", 52 | "fig, ax = plt.subplots(figsize=(7, 7))\n", 53 | "# Origin illustration\n", 54 | "ax.scatter(origin[0], origin[1], c=color)\n", 55 | "ax.annotate(\"\", xy=(0.3, 0.3), xytext=(2, 2), arrowprops=dict(arrowstyle=\"->\"))\n", 56 | "ax.annotate(\"Origin\", xy=(2.3, 2.3), xytext=(2.3, 2.3), bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.3))\n", 57 | "# Vector illustration\n", 58 | "ax.annotate(\"\", xy=vector_xytext, xytext=vector_xy, arrowprops=dict(arrowstyle=\"->\"), c=color)\n", 59 | "ax.annotate(\"[-4, 2]\", xy=(-4.5, 2.5), xytext=(-4.5, 2.5), bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.3))\n", 60 | "\n", 61 | "# Set identical scales for both axes\n", 62 | "ax.set(xlim=(x_min-1, x_max+1), ylim=(y_min-1, y_max+1), aspect=\"equal\")\n", 63 | "\n", 64 | "# Set bottom and left spines as x and y axes of coordinate system\n", 65 | "ax.spines[\"bottom\"].set_position(\"zero\")\n", 66 | "ax.spines[\"left\"].set_position(\"zero\")\n", 67 | "\n", 68 | "# Remode top and right spines\n", 69 | "ax.spines[\"top\"].set_visible(False)\n", 70 | "ax.spines[\"right\"].set_visible(False)\n", 71 | "\n", 72 | "# Set \"x\" and \"y\" labels placed at the end of axes\n", 73 | "ax.set_xlabel('x', size=14, labelpad=-24, x=1.03)\n", 74 | "ax.set_ylabel('y', size=14, labelpad=-21, y=1.02, rotation=0)\n", 75 | "\n", 76 | "# Create custom major ticks to determine position of tick labels\n", 77 | "x_ticks = np.arange(x_min, x_max+1, ticks_freq)\n", 78 | "y_ticks = np.arange(y_min, y_max+1, ticks_freq)\n", 79 | "ax.set_xticks(x_ticks[x_ticks != 0])\n", 80 | "ax.set_yticks(y_ticks[y_ticks != 0])\n", 81 | "\n", 82 | "# Create minor ticks placed at each integer to enable drawing of minor grid\n", 83 | "# lines: note that this has no effect in this example with ticks_frequency=1\n", 84 | "ax.set_xticks(np.arange(x_min, x_max+1), minor=True)\n", 85 | "ax.set_yticks(np.arange(y_min, y_max+1), minor=True)\n", 86 | "\n", 87 | "# Draw major and minor grid lines\n", 88 | "ax.grid(which='both', color='grey', linewidth=1, linestyle='-', alpha=0.2)\n", 89 | "\n", 90 | "# Draw arrows\n", 91 | "arrow_fmt = dict(markersize=4, color='black', clip_on=False)\n", 92 | "ax.plot((1), (0), marker='>', transform=ax.get_yaxis_transform(), **arrow_fmt)\n", 93 | "ax.plot((0), (1), marker='^', transform=ax.get_xaxis_transform(), **arrow_fmt)\n" 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": {}, 99 | "source": [] 100 | } 101 | ], 102 | "metadata": { 103 | "interpreter": { 104 | "hash": "1aad91322e9f4b1bca8b3144bcf5b08e5cbaa8e2651c1f57f28c5e4d868b523d" 105 | }, 106 | "kernelspec": { 107 | "display_name": "Python 3.10.0 64-bit ('ml_env': venv)", 108 | "language": "python", 109 | "name": "python3" 110 | }, 111 | "language_info": { 112 | "codemirror_mode": { 113 | "name": "ipython", 114 | "version": 3 115 | }, 116 | "file_extension": ".py", 117 | "mimetype": "text/x-python", 118 | "name": "python", 119 | "nbconvert_exporter": "python", 120 | "pygments_lexer": "ipython3", 121 | "version": "3.7.11" 122 | }, 123 | "orig_nbformat": 4 124 | }, 125 | "nbformat": 4, 126 | "nbformat_minor": 2 127 | } 128 | -------------------------------------------------------------------------------- /Mathematics/LinearRegression.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | from sklearn import linear_model, datasets 4 | plt.style.use("ggplot") # Prettier Matplotlib Theme 5 | 6 | dataset = datasets.load_diabetes(return_X_y=True) # Loads diabetes dataset 7 | 8 | X = dataset[0] # Assigns the attributes to X 9 | y = dataset[1] # Assigns the labels to y 10 | X = X[:, np.newaxis, 2] # Sets X to a single attribute of the dataset 11 | # Splits attributes into training and test sets 12 | X_train, X_test = X[:-20], X[-20:] # All but the 20 last, All but the first 20 13 | # Splits lables into training and test sets 14 | y_train, y_test = y[:-20], y[-20:] # All but the 20 last, All but the first 20 15 | 16 | # Selects the linear regression machine learning algorithm 17 | model = linear_model.LinearRegression() 18 | # Model trains on the given data 19 | model.fit(X_train, y_train) 20 | # Model predicts the features relative to the training set 21 | prediction = model.predict(X_test) 22 | # Scale the data to highest and lowest difference 23 | data1 = max(max(prediction), max(y_test)) 24 | data2 = min(min(prediction), min(y_test)) 25 | 26 | # Plot our predicted values to the actual values 27 | plt.title("Linear Regression") 28 | plt.scatter(y_test, prediction, marker="x", color="black") # Dots on plot 29 | plt.plot([data1, data2], [data1, data2]) # Line on plot 30 | plt.ylabel("Predictions") 31 | plt.xlabel("Actual") 32 | plt.axis("equal") 33 | plt.show() 34 | 35 | -------------------------------------------------------------------------------- /Mathematics/SigmoidFunction.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | def sigmoid(z): 5 | """ Simple Logistic Sigmoid Function """ 6 | return 1.0 / (1.0 + np.exp(-z)) 7 | 8 | if __name__ == "__main__": 9 | z = np.arange(-7, 7, 0.1) 10 | phi_z = sigmoid(z) 11 | # Plot function 12 | plt.plot(z, phi_z) 13 | plt.axvline(0.0, color="k") 14 | plt.ylim(-0.1, 1.1) 15 | plt.xlabel("z") 16 | plt.ylabel("$\phi{z}$") 17 | # y axis ticks and gridline 18 | plt.yticks([0.0, 0.5, 1.0]) 19 | ax = plt.gca() 20 | ax.yaxis.grid(True) 21 | plt.show() -------------------------------------------------------------------------------- /Neural-Networks/ImageRecognition.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import tensorflow as tf 4 | from tensorflow import keras 5 | 6 | data = keras.datasets.fashion_mnist 7 | (train_images, train_labels), (test_images, test_labels) = data.load_data() 8 | 9 | train_images = train_images / 255.0 10 | test_images = test_images / 255.0 11 | 12 | class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 13 | 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot'] 14 | 15 | model = keras.Sequential([ 16 | keras.layers.Flatten(input_shape=(28,28)), 17 | keras.layers.Dense(128, activation="relu"), 18 | keras.layers.Dense(10, activation="softmax") 19 | ]) 20 | model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"]) 21 | model.fit(train_images, train_labels, epochs=5) 22 | 23 | prediction = model.predict(test_images) 24 | 25 | for i in range(5): 26 | plt.grid(False) 27 | plt.imshow(test_images[i], cmap=plt.cm.binary) 28 | plt.xlabel(f"Actual: {class_names[test_labels[i]]}") 29 | plt.title(f"Prediction: {class_names[np.argmax(prediction[i])]}") 30 | plt.show() 31 | 32 | -------------------------------------------------------------------------------- /Neural-Networks/text/analyse_me: -------------------------------------------------------------------------------- 1 | I was a person that saw all the hype and claims of masterpiece as overreacting and overblown excitement for another Joker based film. 2 | I thought this looked solid at best and even a bit too pretentious in the trailer, but in here to say I was incredibly wrong. 3 | This is a massive achievement of cinema that's extremely rare in a day and age of cgi nonsense and reboots. 4 | While this is somewhat of a reboot of sorts, the standalone origin tale is impeccable from start to finish and echoes resemblance 5 | to the best joker origin comics from the past. Joaquin bleeds, sweats, and cries his every drop into this magnificently dedicated performance. 6 | Heath Ledger would be proud. This is undoubtedly the greatest acting performance since Heath's joker. The directing and writing is slickly 7 | brilliant and the bleak settings and tones are palpable throughout. When this film was over the place was blown away and every audience member 8 | was awestruck that they witnessed a film that could still transport them into a character's world and very existence. 9 | Believe the hype. This is going to be revered as a transcending masterpiece of cinema. -------------------------------------------------------------------------------- /Neural-Networks/text/model.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytesenseidk/Machine-Learning/57386bce7e3bee8cac5bf25357552b5ce5edddb1/Neural-Networks/text/model.h5 -------------------------------------------------------------------------------- /Neural-Networks/text/text_recognition.py: -------------------------------------------------------------------------------- 1 | import tensorflow as td 2 | from tensorflow import keras 3 | import numpy as np 4 | 5 | data = keras.datasets.imdb # Word dataset from imdb movie reviews 6 | 7 | (train_data, train_labels), (test_data, test_labels) = data.load_data(num_words=88000) 8 | 9 | word_index = data.get_word_index() 10 | 11 | # Default values for frequent variables/words 12 | word_index = {key:(value+3) for key, value in word_index.items()} 13 | word_index[""] = 0 # Padding 14 | word_index[""] = 1 # Starting point 15 | word_index[""] = 2 # Unknown characters 16 | word_index[""] = 3 # Unused 17 | 18 | # Swap values & keys, so that the INT value points to the word 19 | reverse_word_index = dict([(value, key) for (key, value) in word_index.items()]) 20 | 21 | # Pad every line to equal length 22 | train_data = keras.preprocessing.sequence.pad_sequences(train_data, value=word_index[""], padding="post", maxlen=250) 23 | test_data = keras.preprocessing.sequence.pad_sequences(test_data, value=word_index[""], padding="post", maxlen=250) 24 | 25 | def decode_review(text): 26 | return " ".join([reverse_word_index.get(i, "?") for i in text]) 27 | 28 | # Train and save a model, if no other is found 29 | if keras.models.load_model("model.h5") == None: 30 | model = keras.Sequential() 31 | model.add(keras.layers.Embedding(88000, 16)) 32 | model.add(keras.layers.GlobalAveragePooling1D()) 33 | model.add(keras.layers.Dense(16, activation="relu")) # Amount of neurons, and 34 | model.add(keras.layers.Dense(1, activation="sigmoid")) 35 | model.summary() 36 | model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"]) 37 | 38 | x_value = train_data[:10000] 39 | x_train = train_data[10000:] 40 | y_value = train_labels[:10000] 41 | y_train = train_labels[10000:] 42 | 43 | fit_model = model.fit(x_train, y_train, epochs=40, batch_size=512, 44 | validation_data=(x_value, y_value), verbose=1) 45 | result = model.evaluate(test_data, test_labels) 46 | 47 | print(result) 48 | model.save("model.h5") 49 | 50 | 51 | def review_encode(string): 52 | encoded = [1] 53 | for word in string: 54 | if word.lower() in word_index: 55 | encoded.append(word_index[word.lower()]) 56 | else: 57 | encoded.append(2) 58 | return encoded 59 | 60 | # Load previously saved model 61 | model = keras.models.load_model("model.h5") 62 | 63 | # Open and format a text 64 | with open("analyse_me", encoding="utf-8") as f: 65 | for line in f.readlines(): 66 | new_line = line.replace(",", "").replace(".", "").replace("(", 67 | "").replace(")", "").replace(":", 68 | "").replace("\"", "").strip().split(" ") 69 | encode = review_encode(new_line) 70 | encode = keras.preprocessing.sequence.pad_sequences([encode], 71 | value=word_index[""], padding="post", maxlen=30) 72 | # Analyse the text for known words 73 | predict = model.predict(encode) 74 | # print(line) 75 | # print(encode) 76 | # print(f"{predict[0]}\n") 77 | for i in encode: 78 | for x in i: 79 | word_id = {value:key for key, value in word_index.items()} 80 | print(word_id) 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Machine Learning and Neural Networks 2 | Different projects made for learning. 3 | 4 | # Description 5 | *Some projects will need some cleaning,* 6 | *README will be updated as well.* 7 | ## Single-Layered Neural Networks 8 | Go to files: [Single-Layered-ANN](https://github.com/bytesenseidk/Machine-Learning/tree/main/Single-Layerd-ANN) 9 | 10 | **LowLevel_SLNN.ipynp:** 11 | - Low level Single-Layer Neural Network 12 | - Mathematical Symbols used in equations 13 | - Learning Model Notes 14 | - Iris Species Prediction: 15 | - Load & Process Dataset 16 | - Train & Predict Species 17 | - Accumulate Accuracies 18 | - Illustrate Species Distribution 19 | - **Perceptron Training Model:** 20 | - Fit-Method 21 | - Convergence 22 | - Convenience Function 23 | ![Alt text](image-2.png) 24 | - **Adaline (ADAptive LInear NEuron):** 25 | - Gradient Descent 26 | - Cost Function 27 | - Feature Scaling 28 | - Large-Scale Machine-Learning 29 | - Stochastic Gradient Descent 30 | ![Alt text](image-1.png) 31 | 32 | # Authors 33 | [Byte Sensei](https://github.com/bytesenseidk) 34 | 35 | # Version History 36 | - 0.1: 37 | * Initial build 38 | - 0.1.1: 39 | * Professionalize Project 40 | # Licence 41 | This project is licenced under the Mozilla Public License 2.0 - see the [LICENCE](https://github.com/bytesenseidk/Machine-Learning/blob/main/LICENCE) for details 42 | -------------------------------------------------------------------------------- /References/arrays.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | # Scalars 4 | dim_0 = np.array(42) 5 | 6 | # UNI-Dimentional Array 7 | dim_1 = np.array([1, 2, 3, 4, 5]) 8 | 9 | # 2-Dimentional Array 10 | dim_2 = np.array([[1, 2, 3], 11 | [4, 5, 6]]) 12 | 13 | # 3-Dimentional Array 14 | dim_3 = np.array([[[1, 2, 3], [4, 5, 6]], 15 | [[1, 2, 3], [4, 5, 6]]]) 16 | 17 | # x-dementional Array 18 | dim_x = np.array([1, 2, 3, 4], ndmin=5) 19 | 20 | # Check amount of dinemtions 21 | check_dim = lambda fun: print(fun.ndim) 22 | check_dim(dim_3) # 3 23 | 24 | print(dim_2) # [[1 2 3] 25 | # [4 5 6]] 26 | print(dim_2.shape) # (2, 3) 27 | print(dim_2.size) # 6 28 | print(dim_2.ndim) # 2 29 | print(dim_2.data) # 30 | print(np.append(dim_1[0], 99)) 31 | print(np.delete(dim_1[0], 1)) -------------------------------------------------------------------------------- /References/matrix.py: -------------------------------------------------------------------------------- 1 | class Matrix_Algebra(object): 2 | 3 | def addition(self, matrix_1, matrix_2): 4 | if len(matrix_1) != len(matrix_2): 5 | return "Matrices not the same dimension" 6 | else: 7 | result = [[matrix_1[row][col] + matrix_2[row][col] for col in range(len(matrix_1[0]))] for row in range(len(matrix_1))] 8 | return result 9 | 10 | def subtraction(self, matrix_1, matrix_2): 11 | if len(matrix_1) != len(matrix_2): 12 | return "Matrices not the same dimension" 13 | else: 14 | result = [[matrix_1[row][col] - matrix_2[row][col] for col in range(len(matrix_1[0]))] for row in range(len(matrix_1))] 15 | return result 16 | 17 | def scalar_multiplication(self, matrix, scalar): 18 | result = [[col * scalar for col in row] for row in matrix] 19 | return result 20 | 21 | 22 | if __name__ == "__main__": 23 | matrix = Matrix_Algebra() 24 | matrix_1_2x2 = [[9, 8], [7, 6]] 25 | matrix_2_2x2 = [[5, 4], [3, 2]] 26 | 27 | matrix.addition(matrix_1_2x2, matrix_2_2x2) 28 | print(matrix.scalar_multiplication(matrix_1_2x2, 2)) 29 | 30 | matrix_1_3x5 = [[1, 2, 3, 4, 5], 31 | [2, 3, 4, 5, 6], 32 | [3, 4, 5, 6, 7]] 33 | 34 | print(matrix.scalar_multiplication(matrix_1_3x5, 2)) 35 | 36 | matrix_2_3x5 = matrix_1_3x5 37 | -------------------------------------------------------------------------------- /References/notes.py: -------------------------------------------------------------------------------- 1 | # Note Section 2 | """ 3 | Eigenvalue: Ez 4 | Eigenvector: Ex 5 | __________________ 6 | - Example 1: 7 | Ez: Ex: 8 | 13 * [3] == [39] 9 | [4] [52] 10 | 11 | - Example 2: 12 | Ez: Ex: 13 | [ 1, 9] * [3] == [39] 14 | [12, 4] [4] [52] 15 | ------- 16 | [13, 13] = Eigenvalue(13) 17 | 18 | 19 | The magnitude of the product of a scalar "k", and a vector "v", is 20 | equal to the absolute value of the scalar and the magnitude of the 21 | origional vector: |k| * ||v|| 22 | sqrt(pow(k, 2)) = |k| 23 | |k| = absolute value of the scalar 24 | - the absolute value of a number is always positive 25 | |-8|(11) = 8(11) = 88 26 | """ 27 | 28 | """ Matrix arithmetic """ 29 | 30 | amanda = [15, 10, 5, 9, 1] 31 | betty = [10, 9, 4, 9, 2] 32 | clark = [20, 0, 0, 23, 1] 33 | dennis = [15, 6, 10, 6, 5] 34 | 35 | pay = [110, 200, 600, 60, 100] 36 | 37 | def total(person, payload): 38 | result = 0 39 | for index, amount in enumerate(person): 40 | result += payload[index] * amount 41 | return result 42 | 43 | amanda_pay = total(amanda, pay) 44 | betty_pay = total(betty, pay) 45 | clark_pay = total(clark, pay) 46 | dennis_pay = total(dennis, pay) 47 | 48 | results = f""" 49 | [ Total Payments ]: 50 | Amanda: {amanda_pay} 51 | Betty: {betty_pay} 52 | Clark: {clark_pay} 53 | Dennis: {dennis_pay} 54 | """ 55 | 56 | 57 | def vectorInMatrix(a, b): 58 | for i, j in zip(a, b): 59 | print(f"list_1: {i}\tlist_2: {j}") 60 | 61 | def numInMatrix(a, b): 62 | for i, j in zip(a, b): 63 | for x, y in zip(i, j): 64 | print(f"list_1: {x}\tlist_2: {y}") 65 | 66 | def addMatrices(a, b): 67 | for i, j in zip(a, b): 68 | for index, x, y in enumerate(zip(i, j)): 69 | a[i][index] = x + y 70 | return a 71 | 72 | 73 | list_1 = [[1, 2, 3],[3, 2, 1], 74 | [1, 2, 3],[3, 2, 1]] 75 | 76 | list_2 = [[4, 5, 6],[6, 5, 4], 77 | [4, 5, 6],[6, 5, 4]] 78 | 79 | 80 | vectorInMatrix(list_1, list_2) 81 | numInMatrix(list_1, list_2) 82 | 83 | """ Matrix arithmetic 84 | matrix multiplication: 85 | 86 | the number of columns in the first matrix must be the same as the number of rows in the second matrix. 87 | 88 | To perform matrix multiplication on m × n - matrix A and p × q - matrix B, 89 | it is necessary that n = p. Furthermore, the resulting matrix A * B has dimension m × q. 90 | 91 | For example, if matrix A has dimension 3 × 4 and matrix B has dimension 4 × 7, 92 | then the product A * B has dimension 3 × 7. But you can’t multiply the matrices in the reverse order. 93 | The product B * A cannot be performed, because matrix B has seven columns and matrix A has three rows. 94 | 95 | if you’re finding the element a 23 in the product matrix A, you get that element by multiplying all the elements 96 | in the second row of the first matrix times the elements in the third column of the second matrix and then adding up the products. 97 | 98 | 99 | A = [[1, 2, 3] 100 | [1, 2, 3] 101 | [1, 2, 3]] 102 | 103 | B = [[4, 5, 6] 104 | [4, 5, 6] 105 | [4, 5, 6]] 106 | 107 | A * B = [[24, 30, 45] 108 | [24, 30, 45] 109 | [24, 30, 45]] 110 | 111 | 112 | A = [[1, 2, 3] 113 | [4, 5, 6] 114 | [7, 8, 9]] 115 | 116 | B = [[9, 6, 3] 117 | [8, 5, 2] 118 | [7, 4, 1]] 119 | 120 | A * B = [[ 46, 28, 10] 121 | [118, 73, 28] 122 | [190, 118, 46]] 123 | 124 | a = 9 + 16 + 21 125 | b = 6 + 10 + 12 126 | c = 3 + 4 + 3 127 | 128 | d = 36 + 40 + 42 129 | e = 24 + 25 + 24 130 | f = 12 + 10 + 6 131 | 132 | g = 63 + 64 + 63 133 | h = 42 + 40 + 36 134 | i = 21 + 16 + 9 135 | 136 | """ 137 | # import numpy as np 138 | 139 | # A = ([1, 2, 3],[4, 5, 6],[7, 8, 9]) 140 | # B = ([9, 6, 3],[8, 5, 2],[7, 4, 1]) 141 | # identity_matrix = ([1, 0, 0],[0, 1, 0],[0, 0, 1]) 142 | 143 | # print(np.dot(A, identity_matrix)) -------------------------------------------------------------------------------- /References/vector.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | from math import hypot, sqrt 3 | 4 | 5 | class VectorArithmetic(object): 6 | def __init__(self, x=0, y=0): 7 | self.x = x 8 | self.y = y 9 | # Parameter count; self, x & y 10 | self.p_count = len(inspect.signature(VectorArithmetic.__init__).parameters.values()) - 1 11 | 12 | 13 | def __repr__(self): 14 | # Representation of the Vector class. 15 | return f"Vector{self.x, self.y}" 16 | 17 | 18 | def __abs__(self): 19 | # Magnitude/Length of the vector ||v|| 20 | return round(hypot(self.x, self.y), 2) 21 | 22 | 23 | def __add__(self, other): 24 | # Addition of vectors(Add 2 objects together). 25 | x = self.x + other.x 26 | y = self.y + other.y 27 | return VectorArithmetic(x, y) 28 | 29 | 30 | def __sub__(self, other): 31 | # Subtraction of vectors. 32 | x = self.x - other.x 33 | y = self.y - other.y 34 | return VectorArithmetic(x, y) 35 | 36 | 37 | def __mul__(self, scalar=1): 38 | # Scalar multiplication(Multiply each value in the vector by a scalar). 39 | return VectorArithmetic(self.x * scalar, self.y * scalar) 40 | 41 | 42 | def __call__(self): 43 | # Describes the instance of the class if called directly. 44 | print(f"Vector Instance: {VectorArithmetic(self.x, self.y)}") 45 | 46 | 47 | def triangle_inequality(self, other): 48 | # The magnitude of the sum of vectors is always less than or equal to the 49 | # sum of the magnitudes of the vectors: ||v + u|| <= ||v|| + ||u|| 50 | vector_0, vector_1 = VectorArithmetic(self.x, self.y), VectorArithmetic(other.x, other.y) 51 | vector_0_mag, vector_1_mag = vector_0.__abs__(), vector_1.__abs__() 52 | mag_of_sum = vector_0.__add__(vector_1).__abs__() 53 | return mag_of_sum <= vector_0_mag + vector_1_mag 54 | 55 | 56 | def arithmetic_mean(self): 57 | # Sum of values divided by the amount of values. 58 | return abs((self.x + self.y) / self.p_count) 59 | 60 | 61 | def geometric_mean(self): 62 | # Sum of values multiplied together, then take a square root 63 | # (for two numbers), cube root (for three numbers) etc. 64 | return round(sqrt(self.x * self.y), 2) 65 | 66 | 67 | if __name__ == "__main__": 68 | vector_0 = VectorArithmetic(7, 10) 69 | vector_1 = VectorArithmetic(3, 7) 70 | methods = { 71 | "added": vector_0.__add__(vector_1), 72 | "subtracted": vector_0.__sub__(vector_1), 73 | "scaled": vector_0.__mul__(5), 74 | "magnitude": vector_0.__abs__(), 75 | "arit_mean": vector_0.arithmetic_mean(), 76 | "geo_mean": vector_0.geometric_mean(), 77 | "inequality": vector_0.triangle_inequality(vector_1) 78 | } 79 | [print(key, ": \t", str(methods[key])) for key in methods] -------------------------------------------------------------------------------- /Single-Layerd-ANN/HighLevel_SLNN.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%matplotlib inline\n", 10 | "\n", 11 | "import numpy as np\n", 12 | "import matplotlib.pyplot as plt\n", 13 | "from sklearn import datasets\n", 14 | "from sklearn.metrics import accuracy_score\n", 15 | "from sklearn.linear_model import Perceptron\n", 16 | "from sklearn.preprocessing import StandardScaler\n", 17 | "from sklearn.model_selection import train_test_split\n", 18 | "from matplotlib.colors import ListedColormap" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "### Method Descriptions:\n", 26 | " - Randomly splits dataset in 70% training data and 30% test data.\n", 27 | " - Shuffles dataset before split with a fixed random seed (random_state=1).\n", 28 | " - This hinders all examples from class 0 and class 1 to end up in the training dataset, and the test dataset would consist of 45 examples from class 2.\n", 29 | " - By providing a fixed random seed for the internal pseudo-random number generator, the dataset is shuffeled prior to splitting.\n", 30 | " - Using such a fixed random_state ensures reproducible results." 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 3, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "iris = datasets.load_iris() # Loads dataset\n", 40 | "\n", 41 | "X = iris.data[:, [2, 3]] # Petal length & Petal width of 150 examples\n", 42 | "y = iris.target # Corresponding class labels of the flowers\n", 43 | "\n", 44 | "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1, stratify=y)" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "### Method Descriptions:\n", 52 | "1. unique(ar, return_index=False, return_inverse=False, return_counts=False, axis=None):\n", 53 | " - Returns the sorted unique elements of an array. There are three optional outputs in addition to the unique elements:\n", 54 | " - The indices of the input array that give the unique values.\n", 55 | " - The indices of the unique array that reconstruct the input array.\n", 56 | " - The number of times each unique value comes up in the input array.\n", 57 | "2. bincount(x, weights=None, minlength=0):\n", 58 | " - Count number of occurrences of each value in array of non-negative ints." 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 4, 64 | "metadata": {}, 65 | "outputs": [ 66 | { 67 | "name": "stdout", 68 | "output_type": "stream", 69 | "text": [ 70 | "Class Labels: [0 1 2]\n", 71 | "Total Label Count: [50 50 50]\n", 72 | "Train Label Count: [35 35 35]\n", 73 | "Test Label Count: [15 15 15]\n" 74 | ] 75 | } 76 | ], 77 | "source": [ 78 | "print(f\"Class Labels: {np.unique(y)}\") \n", 79 | "print(f\"Total Label Count: {np.bincount(y)}\")\n", 80 | "print(f\"Train Label Count: {np.bincount(y_train)}\")\n", 81 | "print(f\"Test Label Count: {np.bincount(y_test)}\")" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "### Method Descriptions:\n", 89 | "1. StandardScaler(*, copy=True, with_mean=True, with_std=True):\n", 90 | " - Standardize features by removing the mean and scaling to unit variance.\n", 91 | " - The standard score of a sample x is calculated as:\n", 92 | " - $z = (x - u) / s$\n", 93 | " - $u$ is the mean of the training samples or zero if with_mean=False.\n", 94 | " - $s$ is the standard deviation of the training samples or one if with_std=False.\n", 95 | "2. scalar.fit(X, y=None, sample_weight=None):\n", 96 | " - Compute the mean and std to be used for later scaling.\n", 97 | "3. scalar.transform(X, copy=None):\n", 98 | " - Perform standardization by centering and scaling.\n", 99 | "4. perceptron.fit(X, y, coef_init=None, intercept_init=None, sample_weight=None):\n", 100 | " - Fit linear model with Stochastic Gradient Descent.\n", 101 | "5. perceptron.predict(X):\n", 102 | " - Predict class labels for samples in X." 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": 5, 108 | "metadata": {}, 109 | "outputs": [], 110 | "source": [ 111 | "scalar = StandardScaler()\n", 112 | "scalar.fit(X_train)\n", 113 | "X_train_std = scalar.transform(X_train)\n", 114 | "X_test_std = scalar.transform(X_test)\n", 115 | "\n", 116 | "perceptron = Perceptron(eta0=0.1, random_state=1)\n", 117 | "perceptron.fit(X_train_std, y_train)\n", 118 | "\n", 119 | "y_prediction = perceptron.predict(X_test_std)" 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": {}, 125 | "source": [ 126 | "### Method Descriptions:\n", 127 | "1. accuracy_score(y_true, y_pred, *, normalize=True, sample_weight=None):\n", 128 | " - Accuracy classification score.\n", 129 | " - In multilabel classification, this function computes subset accuracy:\n", 130 | " - The set of labels predicted for a sample must exactly match the corresponding set of labels in y_true." 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": 6, 136 | "metadata": {}, 137 | "outputs": [ 138 | { 139 | "name": "stdout", 140 | "output_type": "stream", 141 | "text": [ 142 | "Misclassified Examples: 1\n", 143 | "Model Accuracy: 97.78%\n" 144 | ] 145 | } 146 | ], 147 | "source": [ 148 | "print(f\"Misclassified Examples: {(y_test != y_prediction).sum()}\")\n", 149 | "print(f\"Model Accuracy: {round((accuracy_score(y_test, y_prediction)*100), 2)}%\")" 150 | ] 151 | }, 152 | { 153 | "cell_type": "markdown", 154 | "metadata": {}, 155 | "source": [ 156 | "### Method Descriptions:\n", 157 | "1. ndarray.min(axis=None, out=None, keepdims=False, initial=, where=True):\n", 158 | " - Return the minimum along a given axis.\n", 159 | "2. ndarray.max(axis=None, out=None, keepdims=False, initial=, where=True):\n", 160 | " - Return the maximum along a given axis.\n", 161 | "3. ListedColormap(colors, name='from_list', N=None):\n", 162 | " - Colormap object generated from a list of colors.\n", 163 | " - This may be most useful when indexing directly into a colormap, but it can also be used to generate special colormaps for ordinary mapping.\n", 164 | "4. meshgrid(*xi, copy=True, sparse=False, indexing='xy'):\n", 165 | " - Return coordinate matrices from coordinate vectors.\n", 166 | " - Make N-D coordinate arrays for vectorized evaluations of N-D scalar/vector fields over N-D grids, given one-dimensional coordinate arrays x1, x2,…, xn.\n", 167 | "5. arange([start, ]stop, [step, ]dtype=None, *, like=None):\n", 168 | " - Return evenly spaced values within a given interval.\n", 169 | " - Values are generated within the half-open interval [start, stop) (in other words, the interval including start but excluding stop).\n", 170 | " - For integer arguments the function is equivalent to the Python built-in range function, but returns an ndarray rather than a list.\n", 171 | " - When using a non-integer step, such as 0.1, the results will often not be consistent. It is better to use numpy.linspace for these cases.\n", 172 | "6. ndarray.ravel([order]):\n", 173 | " - Return a flattened array.\n", 174 | "7. ndarray.T:\n", 175 | " - The transposed array. (Turns row-array to column-array and vice-versa)\n", 176 | "8. ndarray.shape:\n", 177 | " - Tuple of array dimensions.\n", 178 | " - The shape property is usually used to get the current shape of an array, but may also be used to reshape the array in-place by assigning a tuple of array dimensions to it.\n", 179 | " - As with numpy.reshape, one of the new shape dimensions can be -1, in which case its value is inferred from the size of the array and the remaining dimensions.\n", 180 | " - Reshaping an array in-place will fail if a copy is required.\n", 181 | "9. reshape(a, newshape, order='C'):\n", 182 | " - Gives a new shape to an array without changing its data.\n", 183 | "10. contourf(*args, data=None, **kwargs):\n", 184 | " - Plot filled contours.\n", 185 | "11. xlim & ylim(*args, **kwargs):\n", 186 | " - Get or set the x or y limits of the current axes." 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": 7, 192 | "metadata": {}, 193 | "outputs": [], 194 | "source": [ 195 | "def plot_decision_regions(X, y, classifier, test_idx=None, resolution=0.02):\n", 196 | " # Setup marker generator and color map\n", 197 | " markers = (\"s\", \"x\", \"o\", \"^\", \"v\")\n", 198 | " colors = (\"red\", \"blue\", \"lightgreen\", \"gray\", \"cyan\")\n", 199 | " cmap = ListedColormap(colors[:len(np.unique(y))])\n", 200 | "\n", 201 | " # Plot decision surface\n", 202 | " x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1\n", 203 | " x2_min, x2_max = X[:, 0].min() - 1, X[:, 0].max() + 1\n", 204 | " xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max, resolution))\n", 205 | " Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)\n", 206 | " Z = Z.reshape(xx1.shape)\n", 207 | " plt.contourf(xx1, xx2, Z, alpha=0.3, cmap=cmap)\n", 208 | " plt.xlim(xx1.min(), xx1.max())\n", 209 | " plt.ylim(xx2.min(), xx2.max())\n", 210 | "\n", 211 | " for index, lbl in enumerate(np.unique(y)):\n", 212 | " plt.scatter(x=X[y == lbl, 0], y=X[y == lbl, 1], alpha=0.8, \n", 213 | " c=colors[index], marker=markers[index], label=lbl, \n", 214 | " edgecolor=\"black\")\n", 215 | " \n", 216 | " # Highlight test examples\n", 217 | " if test_idx:\n", 218 | " # Plot all examples\n", 219 | " X_test, y_test = X[test_idx, :], y[test_idx]\n", 220 | "\n", 221 | " plt.scatter(X_test[:, 0], X_test[:, 1], c=\"black\", edgecolor=\"black\", \n", 222 | " alpha=1.0, linewidth=1, marker=\"o\", s=25, label=\"test set\")" 223 | ] 224 | }, 225 | { 226 | "cell_type": "markdown", 227 | "metadata": {}, 228 | "source": [ 229 | "### Method Descriptions:\n", 230 | "1. vstack(tup):\n", 231 | " - Stack arrays in sequence vertically (row wise).\n", 232 | " - This is equivalent to concatenation along the first axis after 1-D arrays of shape (N,) have been reshaped to (1,N). Rebuilds arrays divided by vsplit.\n", 233 | " - This function makes most sense for arrays with up to 3 dimensions.\n", 234 | "2. hstack(tup):\n", 235 | " - Stack arrays in sequence horizontally (column wise).\n", 236 | " - This is equivalent to concatenation along the second axis, except for 1-D arrays where it concatenates along the first axis. Rebuilds arrays divided by hsplit.\n", 237 | " - This function makes most sense for arrays with up to 3 dimensions." 238 | ] 239 | }, 240 | { 241 | "cell_type": "code", 242 | "execution_count": 8, 243 | "metadata": {}, 244 | "outputs": [ 245 | { 246 | "name": "stderr", 247 | "output_type": "stream", 248 | "text": [ 249 | "C:\\Users\\ANONYM~1\\AppData\\Local\\Temp/ipykernel_16728/2329631292.py:18: UserWarning: You passed a edgecolor/edgecolors ('black') for an unfilled marker ('x'). Matplotlib is ignoring the edgecolor in favor of the facecolor. This behavior may change in the future.\n", 250 | " plt.scatter(x=X[y == lbl, 0], y=X[y == lbl, 1], alpha=0.8,\n" 251 | ] 252 | }, 253 | { 254 | "data": { 255 | "image/png": "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", 256 | "text/plain": [ 257 | "
" 258 | ] 259 | }, 260 | "metadata": { 261 | "needs_background": "light" 262 | }, 263 | "output_type": "display_data" 264 | } 265 | ], 266 | "source": [ 267 | "X_combined_std = np.vstack((X_train_std, X_test_std))\n", 268 | "y_combined = np.hstack((y_train, y_test))\n", 269 | "plot_decision_regions(X=X_combined_std, y=y_combined, classifier=perceptron, test_idx=range(105, 150))\n", 270 | "plt.xlabel(\"Petal Length [Standardized]\")\n", 271 | "plt.ylabel(\"Petal Width [Standardized]\")\n", 272 | "plt.legend(loc=\"upper left\")\n", 273 | "plt.tight_layout()" 274 | ] 275 | } 276 | ], 277 | "metadata": { 278 | "interpreter": { 279 | "hash": "1aad91322e9f4b1bca8b3144bcf5b08e5cbaa8e2651c1f57f28c5e4d868b523d" 280 | }, 281 | "kernelspec": { 282 | "display_name": "Python 3.10.0 64-bit ('ml_env': venv)", 283 | "language": "python", 284 | "name": "python3" 285 | }, 286 | "language_info": { 287 | "codemirror_mode": { 288 | "name": "ipython", 289 | "version": 3 290 | }, 291 | "file_extension": ".py", 292 | "mimetype": "text/x-python", 293 | "name": "python", 294 | "nbconvert_exporter": "python", 295 | "pygments_lexer": "ipython3", 296 | "version": "3.10.0" 297 | }, 298 | "orig_nbformat": 4 299 | }, 300 | "nbformat": 4, 301 | "nbformat_minor": 2 302 | } 303 | -------------------------------------------------------------------------------- /Single-Layerd-ANN/adaline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytesenseidk/Machine-Learning/57386bce7e3bee8cac5bf25357552b5ce5edddb1/Single-Layerd-ANN/adaline.png -------------------------------------------------------------------------------- /Single-Layerd-ANN/perceptron.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytesenseidk/Machine-Learning/57386bce7e3bee8cac5bf25357552b5ce5edddb1/Single-Layerd-ANN/perceptron.jpg -------------------------------------------------------------------------------- /Supervised/CancerClassification.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | from sklearn import datasets 4 | from sklearn.linear_model import Perceptron 5 | from sklearn.model_selection import train_test_split 6 | 7 | breast = datasets.load_breast_cancer() 8 | X = breast.data 9 | y = breast.target 10 | 11 | acc_list = [] 12 | misclassifications = 0 13 | tumor_type = list(breast.target_names) 14 | 15 | # Train and print model results 16 | for i in range(50): 17 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1) 18 | model = Perceptron(eta0=0.01, random_state=1) 19 | model.fit(X_train, y_train) 20 | 21 | cur_acc = model.score(X_test, y_test) 22 | acc_list.append(cur_acc) 23 | 24 | prediction = model.predict(X_test) 25 | if tumor_type[prediction[i]] != tumor_type[y_test[i]]: 26 | misclassifications += 1 27 | 28 | print(f"Prediction:\t{tumor_type[prediction[i]].ljust(10)}"\ 29 | f"\tActual: {tumor_type[y_test[i]].ljust(10)}"\ 30 | f"\tAccuracy: {str(round(cur_acc * 100, 2)).ljust(5)}%") 31 | 32 | avg_acc = round(sum(acc_list) / len(acc_list), 2) 33 | 34 | print(f"\nAverage Accuracy: {avg_acc * 100}%") 35 | print(f"Misclassifications: {misclassifications}") 36 | 37 | # Plot classifications 38 | features = breast.data.T 39 | plot_x = features[0] 40 | plot_y = features[1] 41 | area = 100 + features[3] 42 | plt.scatter(plot_x, plot_y, alpha=0.2, s=area, c=breast.target, cmap="viridis") 43 | plt.xlabel(breast.feature_names[0]) 44 | plt.ylabel(breast.feature_names[1]) 45 | 46 | -------------------------------------------------------------------------------- /Supervised/Classification.py: -------------------------------------------------------------------------------- 1 | import os 2 | import tensorflow as tf 3 | import matplotlib.pyplot as plt 4 | from tensorflow import keras 5 | from tensorflow.keras import layers 6 | 7 | 8 | num_skipped = 0 9 | for folder_name in ("Cat", "Dog"): 10 | folder_path = os.path.join("PetImages", folder_name) 11 | for fname in os.listdir(folder_path): 12 | fpath = os.path.join(folder_path, fname) 13 | try: 14 | fobj = open(fpath, "rb") 15 | is_jfif = tf.compat.as_bytes("JFIF") in fobj.peek(10) 16 | finally: 17 | fobj.close() 18 | 19 | if not is_jfif: 20 | num_skipped += 1 21 | # Delete corrupted image 22 | os.remove(fpath) 23 | 24 | print("Deleted %d images" % num_skipped) 25 | 26 | image_size = (180, 180) 27 | batch_size = 32 28 | 29 | train_ds = tf.keras.preprocessing.image_dataset_from_directory( 30 | "PetImages", 31 | validation_split=0.2, 32 | subset="training", 33 | seed=1337, 34 | image_size=image_size, 35 | batch_size=batch_size, 36 | ) 37 | val_ds = tf.keras.preprocessing.image_dataset_from_directory( 38 | "PetImages", 39 | validation_split=0.2, 40 | subset="validation", 41 | seed=1337, 42 | image_size=image_size, 43 | batch_size=batch_size, 44 | ) 45 | 46 | plt.figure(figsize=(10, 10)) 47 | for images, labels in train_ds.take(1): 48 | for i in range(9): 49 | ax = plt.subplot(3, 3, i + 1) 50 | plt.imshow(images[i].numpy().astype("uint8")) 51 | plt.title(int(labels[i])) 52 | plt.axis("off") 53 | 54 | data_augmentation = keras.Sequential( 55 | [ 56 | layers.experimental.preprocessing.RandomFlip("horizontal"), 57 | layers.experimental.preprocessing.RandomRotation(0.1), 58 | ] 59 | ) 60 | 61 | plt.figure(figsize=(10, 10)) 62 | for images, _ in train_ds.take(1): 63 | for i in range(9): 64 | augmented_images = data_augmentation(images) 65 | ax = plt.subplot(3, 3, i + 1) 66 | plt.imshow(augmented_images[0].numpy().astype("uint8")) 67 | plt.axis("off") 68 | 69 | augmented_train_ds = train_ds.map( 70 | lambda x, y: (data_augmentation(x, training=True), y) 71 | ) 72 | 73 | train_ds = train_ds.prefetch(buffer_size=32) 74 | val_ds = val_ds.prefetch(buffer_size=32) 75 | 76 | def make_model(input_shape, num_classes): 77 | inputs = keras.Input(shape=input_shape) 78 | # Image augmentation block 79 | x = data_augmentation(inputs) 80 | 81 | # Entry block 82 | x = layers.experimental.preprocessing.Rescaling(1.0 / 255)(x) 83 | x = layers.Conv2D(32, 3, strides=2, padding="same")(x) 84 | x = layers.BatchNormalization()(x) 85 | x = layers.Activation("relu")(x) 86 | 87 | x = layers.Conv2D(64, 3, padding="same")(x) 88 | x = layers.BatchNormalization()(x) 89 | x = layers.Activation("relu")(x) 90 | 91 | previous_block_activation = x # Set aside residual 92 | 93 | for size in [128, 256, 512, 728]: 94 | x = layers.Activation("relu")(x) 95 | x = layers.SeparableConv2D(size, 3, padding="same")(x) 96 | x = layers.BatchNormalization()(x) 97 | 98 | x = layers.Activation("relu")(x) 99 | x = layers.SeparableConv2D(size, 3, padding="same")(x) 100 | x = layers.BatchNormalization()(x) 101 | 102 | x = layers.MaxPooling2D(3, strides=2, padding="same")(x) 103 | 104 | # Project residual 105 | residual = layers.Conv2D(size, 1, strides=2, padding="same")( 106 | previous_block_activation 107 | ) 108 | x = layers.add([x, residual]) # Add back residual 109 | previous_block_activation = x # Set aside next residual 110 | 111 | x = layers.SeparableConv2D(1024, 3, padding="same")(x) 112 | x = layers.BatchNormalization()(x) 113 | x = layers.Activation("relu")(x) 114 | 115 | x = layers.GlobalAveragePooling2D()(x) 116 | if num_classes == 2: 117 | activation = "sigmoid" 118 | units = 1 119 | else: 120 | activation = "softmax" 121 | units = num_classes 122 | 123 | x = layers.Dropout(0.5)(x) 124 | outputs = layers.Dense(units, activation=activation)(x) 125 | return keras.Model(inputs, outputs) 126 | 127 | 128 | model = make_model(input_shape=image_size + (3,), num_classes=2) 129 | keras.utils.plot_model(model, show_shapes=True) 130 | 131 | epochs = 50 132 | 133 | callbacks = [ 134 | keras.callbacks.ModelCheckpoint("save_at_{epoch}.h5"), 135 | ] 136 | model.compile( 137 | optimizer=keras.optimizers.Adam(1e-3), 138 | loss="binary_crossentropy", 139 | metrics=["accuracy"], 140 | ) 141 | model.fit( 142 | train_ds, epochs=epochs, callbacks=callbacks, validation_data=val_ds, 143 | ) 144 | 145 | img = keras.preprocessing.image.load_img( 146 | "PetImages/Cat/6779.jpg", target_size=image_size 147 | ) 148 | img_array = keras.preprocessing.image.img_to_array(img) 149 | img_array = tf.expand_dims(img_array, 0) # Create batch axis 150 | 151 | predictions = model.predict(img_array) 152 | score = predictions[0] 153 | print( 154 | "This image is %.2f percent cat and %.2f percent dog." 155 | % (100 * (1 - score), 100 * score) 156 | ) 157 | -------------------------------------------------------------------------------- /Supervised/LinearRegression_Diabetes.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 116, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%matplotlib inline\n", 10 | "\n", 11 | "import numpy as np\n", 12 | "import pandas as pd\n", 13 | "import matplotlib.pyplot as plt\n", 14 | "from sklearn import linear_model, datasets\n", 15 | "\n", 16 | "plt.style.use(\"ggplot\")" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 117, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "X, y = datasets.load_diabetes(return_X_y=True)\n", 26 | "X = X[:, np.newaxis, 2]\n", 27 | "\n", 28 | "X_train, X_test = X[:-20], X[-20:]\n", 29 | "y_train, y_test = y[:-20], y[-20:]\n", 30 | "\n", 31 | "model = linear_model.LinearRegression()\n", 32 | "model.fit(X_train, y_train)\n", 33 | "\n", 34 | "prediction = model.predict(X_test)" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 118, 40 | "metadata": {}, 41 | "outputs": [ 42 | { 43 | "data": { 44 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXcAAAEJCAYAAABv6GdPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8/fFQqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAwXklEQVR4nO3de1xUdf7H8dcBREBkYMQbqCVqupqGK5qahRe6amVW+8jK0ijX1FpvletWaNZ6CbwlllukWf5SW0NbW7sgirZqYt4vm5qXFVG5DE6CIrfz+4NmYgSZgbkdhs/z8eiRM3xn5j0DfvzyOd/zPYqqqipCCCE8ipe7AwghhHA8Ke5CCOGBpLgLIYQHkuIuhBAeSIq7EEJ4ICnuQgjhgaS4C4fo378/zz//vLtj1HvTp0+nffv27o4hNECRde7CFiNHjiQjI4OUlJQqv24wGPDx8SEoKMjFyWy3fPlyRo0aZb4dGhpKZGQkM2fOpHfv3m5M5jj5+fkUFhYSGhrq7ijCzWTmLhxCr9drprAXFRXd8Gve3t6cP3+e8+fPs2nTJoKDg7n//vvJyspyeq7i4mKnv0ZgYKAUdgFIcRcOcn1bxnR75syZtGjRAr1ezzPPPEN+fr7F41atWkVkZCR+fn7cfPPNTJo0iYKCAvPXv//+e/r3749er0en0xEdHc2uXbssnkNRFBYtWsSTTz6JTqdjxIgR1WZt0aIFLVq0oFu3brz55ptcunSJH3/80fz1EydO8OijjxIcHExISAj33HMPBw8etHiOzz//nHbt2uHn50ffvn3ZsGEDiqLwww8/ALBlyxYUReHrr7+mX79++Pn58dFHHwHw3nvv0alTJ/z8/OjQoQPvvPMOJSUl5udev3493bt3JyAggODgYHr16sXevXuB8n8gJk2aRKtWrWjYsCEtW7bkiSeeMD+2qrbMJ598QufOnfH19aVVq1a8/vrrFq9n6/dK1C1S3IXT/POf/8RgMLBlyxZWrVrFhg0bmDNnjvnry5cv58UXX2Ty5MkcOXKEFStWkJKSwpgxY8xj8vPzGTt2LDt27GD79u106NCB++67j9zcXIvXmjFjBn379mXPnj28/fbbNuUrKCjg448/BsDX1xeAixcv0q9fP5o1a8a2bdvYuXMnHTt2pH///mRnZwPw008/8dRTTzF8+HD279/Pq6++yoQJE6p8jcmTJ/Paa69x9OhRHnzwQaZPn058fDyzZs3i6NGjLFy4kKVLlzJjxgwALly4wOOPP87w4cM5fPgwO3bsYMKECfj4+ADl/zCsWbOGzz77jOPHj/PVV19V21L6+uuvee655xgxYgSHDh0iISGBxMRE8+uZWPteiTpIFcIGzz77rDpo0KAbfj06OlqNjY21uN2tWzeLMWPGjFF79+5tvn3TTTep77//vsWYtLQ0FVANBkOVr1NaWqoGBwern332mfk+QH3uueesvodly5apgNqoUSO1UaNGKqAC6u23364WFxerqqqqcXFx6u23327xuLKyMjUiIkKdP3++qqqq+uSTT6r9+vWzGPP++++rgLpt2zZVVVV18+bNKqCuWLHCPKagoED19/dXN27caPHYTz75RNXpdKqqquqePXtUQD116lSV7+Hll19WBwwYoJaVlVX59bi4OLVdu3bm2/369VMff/xxizELFixQ/fz81GvXrqmqatv3StQ9MnMXTnPbbbdZ3A4LC+PixYsAZGdnc+bMGSZNmkRgYKD5v/vvvx8ob40AnDp1ihEjRtC+fXuCgoIICgrCaDRy5swZi+fu1auXTZm8vb3Zt28fP/30E59++ilt27bl008/Nc+M09PT+emnnywyNW7cmNOnT3P8+HEAjhw5Umm23KdPnypfr2Kuw4cPc/XqVR599FGL5//zn/+M0WgkOzubbt26ce+993LrrbfyyCOPsHDhQs6ePWt+jlGjRnHw4EHat2/PmDFjWLt2bbXHGA4fPsxdd91lcV90dDSFhYX88ssv5vuq+16JusnH3QGE5zK1OkwURaGsrAzA/P+FCxcyYMCASo9t1aoVAEOGDCE0NJTExERat26Nr68v/fr1q1TQGjVqZHMuU0+6Y8eOXL16laFDh7J37158fX0pKytj0KBBLF68uNLjdDqdxXuxRcVcpvf8xRdfcMstt1Qaq9fr8fb2ZuPGjaSnp5OSksLatWuZOnUqX3zxBUOGDCEyMpJTp07x/fffs3nzZv7yl7/wxhtvsHPnTrsOaFf3vRJ1k8zchVs0b96c1q1b8/PPP9O+fftK//n5+ZGbm8uRI0eYOnUq9957L507d8bPz8+hK1uee+45rly5Yi7mUVFRHD58mFatWlXK1LRpUwA6d+7Mjh07LJ5n586dVl+rS5cu+Pn5cfLkySrfs7e3N1BeWHv1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", 45 | "text/plain": [ 46 | "
" 47 | ] 48 | }, 49 | "metadata": {}, 50 | "output_type": "display_data" 51 | } 52 | ], 53 | "source": [ 54 | "plt.title(\"Linear Regression\")\n", 55 | "plt.scatter(X_test, y_test, color=\"black\", marker=\"x\")\n", 56 | "plt.plot(X_test, prediction, color=\"blue\", linewidth=3)\n", 57 | "plt.xticks()\n", 58 | "plt.yticks()\n", 59 | "plt.show()" 60 | ] 61 | } 62 | ], 63 | "metadata": { 64 | "interpreter": { 65 | "hash": "5826022c13cf670f25f82c54601002af42321e6e77593e3891ed52ffe2de205c" 66 | }, 67 | "kernelspec": { 68 | "display_name": "Python 3.8.1 64-bit ('azureml_py38_tensorflow': conda)", 69 | "language": "python", 70 | "name": "python3" 71 | }, 72 | "language_info": { 73 | "codemirror_mode": { 74 | "name": "ipython", 75 | "version": 3 76 | }, 77 | "file_extension": ".py", 78 | "mimetype": "text/x-python", 79 | "name": "python", 80 | "nbconvert_exporter": "python", 81 | "pygments_lexer": "ipython3", 82 | "version": "3.10.0" 83 | }, 84 | "orig_nbformat": 4 85 | }, 86 | "nbformat": 4, 87 | "nbformat_minor": 2 88 | } 89 | -------------------------------------------------------------------------------- /Supervised/LinearRegression_Grades.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 35, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%matplotlib inline\n", 10 | "\n", 11 | "import sklearn\n", 12 | "import numpy as np\n", 13 | "import pandas as pd\n", 14 | "import matplotlib.pyplot as plt\n", 15 | "from sklearn import linear_model\n", 16 | "\n", 17 | "plt.style.use(\"ggplot\")" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 36, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "dataset = pd.read_csv(\"student-mat.csv\", sep=\";\")\n", 27 | "data = dataset[[\"G1\", \"G2\", \"G3\", \"studytime\", \"failures\", \"absences\"]]\n", 28 | "predict = \"G3\"" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": 37, 34 | "metadata": {}, 35 | "outputs": [ 36 | { 37 | "name": "stderr", 38 | "output_type": "stream", 39 | "text": [ 40 | "C:\\Users\\lars29i0\\AppData\\Local\\Temp/ipykernel_14676/1843668013.py:1: FutureWarning: In a future version of pandas all arguments of DataFrame.drop except for the argument 'labels' will be keyword-only\n", 41 | " X = np.array(data.drop([predict], 1)) # Attributes\n" 42 | ] 43 | } 44 | ], 45 | "source": [ 46 | "X = np.array(data.drop([predict], 1)) # Attributes\n", 47 | "y = np.array(data[predict]) # Labels\n", 48 | "\n", 49 | "# Split dataset in 4 arrays & test on 10% of the data\n", 50 | "x_train, x_test, y_train, y_test = sklearn.model_selection.train_test_split(X, y, test_size=0.1)" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 38, 56 | "metadata": {}, 57 | "outputs": [ 58 | { 59 | "name": "stdout", 60 | "output_type": "stream", 61 | "text": [ 62 | "Model Accuracy: 70.92%\n" 63 | ] 64 | } 65 | ], 66 | "source": [ 67 | "linear = linear_model.LinearRegression()\n", 68 | "linear.fit(x_train, y_train)\n", 69 | "accuracy = linear.score(x_test, y_test) # Accuracy of model\n", 70 | "\n", 71 | "print(f\"Model Accuracy: {round(accuracy * 100, 2)}%\")" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 39, 77 | "metadata": {}, 78 | "outputs": [ 79 | { 80 | "name": "stdout", 81 | "output_type": "stream", 82 | "text": [ 83 | "Prediction: -1 \t Actual: 0\n", 84 | "Prediction: 15 \t Actual: 15\n", 85 | "Prediction: 8 \t Actual: 8\n", 86 | "Prediction: 13 \t Actual: 13\n", 87 | "Prediction: 8 \t Actual: 9\n", 88 | "Prediction: 18 \t Actual: 18\n", 89 | "Prediction: 16 \t Actual: 17\n", 90 | "Prediction: 13 \t Actual: 15\n", 91 | "Prediction: 8 \t Actual: 10\n", 92 | "Prediction: 14 \t Actual: 15\n", 93 | "Best accuracy: 91.12%\n" 94 | ] 95 | } 96 | ], 97 | "source": [ 98 | "best = 0\n", 99 | "\n", 100 | "for _ in range(100):\n", 101 | " x_train, x_test, y_train, y_test = sklearn.model_selection.train_test_split(X, y, test_size=0.3)\n", 102 | " training_model = linear_model.LinearRegression()\n", 103 | " training_model.fit(x_train, y_train)\n", 104 | " accuracy = linear.score(x_test, y_test)\n", 105 | " if accuracy > best:\n", 106 | " best = accuracy\n", 107 | "\n", 108 | "predictions = training_model.predict(x_test)\n", 109 | "for i in range(10):\n", 110 | " print(f\"Prediction: {int(predictions[i])} \\t Actual: {y_test[i]}\")\n", 111 | "print(f\"Best accuracy: {round((best * 100), 2)}%\")" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": 40, 117 | "metadata": {}, 118 | "outputs": [ 119 | { 120 | "data": { 121 | "text/plain": [ 122 | "[]" 123 | ] 124 | }, 125 | "execution_count": 40, 126 | "metadata": {}, 127 | "output_type": "execute_result" 128 | }, 129 | { 130 | "data": { 131 | "image/png": "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", 132 | "text/plain": [ 133 | "
" 134 | ] 135 | }, 136 | "metadata": {}, 137 | "output_type": "display_data" 138 | } 139 | ], 140 | "source": [ 141 | "_X, _y = data[\"G1\"], data[\"G3\"]\n", 142 | "m, b = np.polyfit(data[\"G1\"], data[\"G3\"], 1)\n", 143 | "\n", 144 | "plt.title(\"Linear Regression\")\n", 145 | "plt.xlabel(\"Actual Grade\")\n", 146 | "plt.ylabel(\"Prediction\")\n", 147 | "plt.scatter(_X, _y, marker=\"x\")\n", 148 | "plt.plot(_X, m * _X + b)" 149 | ] 150 | } 151 | ], 152 | "metadata": { 153 | "interpreter": { 154 | "hash": "5826022c13cf670f25f82c54601002af42321e6e77593e3891ed52ffe2de205c" 155 | }, 156 | "kernelspec": { 157 | "display_name": "Python 3.8.1 64-bit ('azureml_py38_tensorflow': conda)", 158 | "language": "python", 159 | "name": "python3" 160 | }, 161 | "language_info": { 162 | "codemirror_mode": { 163 | "name": "ipython", 164 | "version": 3 165 | }, 166 | "file_extension": ".py", 167 | "mimetype": "text/x-python", 168 | "name": "python", 169 | "nbconvert_exporter": "python", 170 | "pygments_lexer": "ipython3", 171 | "version": "3.10.0" 172 | }, 173 | "orig_nbformat": 4 174 | }, 175 | "nbformat": 4, 176 | "nbformat_minor": 2 177 | } 178 | -------------------------------------------------------------------------------- /Supervised/ModelTester.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 81, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%matplotlib inline\n", 10 | "\n", 11 | "import numpy as np\n", 12 | "import pandas as pd\n", 13 | "import matplotlib.pyplot as plt\n", 14 | "from matplotlib import style\n", 15 | "from sklearn import datasets\n", 16 | "from sklearn.svm import SVC\n", 17 | "from sklearn.cluster import KMeans\n", 18 | "from sklearn.metrics import accuracy_score\n", 19 | "from sklearn.preprocessing import StandardScaler\n", 20 | "from sklearn.model_selection import train_test_split\n", 21 | "\n", 22 | "style.use(\"ggplot\")\n", 23 | "\n", 24 | "dataset = datasets.load_wine()\n", 25 | "\n", 26 | "X = dataset.data\n", 27 | "y = dataset.target" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 82, 33 | "metadata": {}, 34 | "outputs": [ 35 | { 36 | "name": "stdout", 37 | "output_type": "stream", 38 | "text": [ 39 | "Prediction:\t\tActual:\t\t\tAccuracy:\n", 40 | "malic_acid\t\tmalic_acid\t\t94.44%\n", 41 | "alcohol \t\talcohol \t\t90.74%\n", 42 | "malic_acid\t\tash \t\t88.89%\n", 43 | "malic_acid\t\tmalic_acid\t\t94.44%\n", 44 | "alcohol \t\talcohol \t\t92.59%\n", 45 | "malic_acid\t\tmalic_acid\t\t90.74%\n", 46 | "Average Accuracy: 94.81%\n", 47 | "Misclassifications: 8 out of 50 examples\n" 48 | ] 49 | } 50 | ], 51 | "source": [ 52 | "\n", 53 | "class SupportVectorClassifier(object):\n", 54 | " def __init__(self, dataset, X, y, n_iter=45):\n", 55 | " self.X = X\n", 56 | " self.y = y\n", 57 | " self.dataset = dataset\n", 58 | " self.n_iter = n_iter\n", 59 | " \n", 60 | " self.classes = list(dataset.feature_names)\n", 61 | " self.model = SVC(kernel=\"linear\", C=3)\n", 62 | " self.results = []\n", 63 | " self.predictions = []\n", 64 | " self.misclassifications = 0\n", 65 | " \n", 66 | " self.train_model()\n", 67 | " \n", 68 | " \n", 69 | " def train_model(self):\n", 70 | " self.results.append(\"Prediction:\\t\\tActual:\\t\\t\\tAccuracy:\")\n", 71 | " for i in range(self.n_iter):\n", 72 | " X_train, X_test, y_train, y_test = train_test_split(self.X, self.y, test_size=0.3) \n", 73 | " self.model.fit(X_train, y_train)\n", 74 | "\n", 75 | " pred = self.model.predict(X_test)\n", 76 | " if self.classes[pred[i]] != self.classes[y_test[i]]:\n", 77 | " self.misclassifications += 1\n", 78 | " \n", 79 | " acc = round(accuracy_score(y_test, pred) * 100, 2)\n", 80 | " self.predictions.append(acc)\n", 81 | " \n", 82 | " self.results.append(f\"{self.classes[pred[i]].ljust(10)}\\t\\t{self.classes[y_test[i]].ljust(10)}\\t\\t{acc}%\")\n", 83 | "\n", 84 | "\n", 85 | " def average_accuracy(self):\n", 86 | " self.predictions = sorted(self.predictions)\n", 87 | " scaled_data = self.predictions[5:-5]\n", 88 | " return round(sum(scaled_data) / len(scaled_data), 2)\n", 89 | " \n", 90 | " \n", 91 | "if __name__ == \"__main__\":\n", 92 | " svc = SupportVectorClassifier(dataset, X, y, n_iter=50)\n", 93 | " [print(svc.results[i]) for i in range(7)]\n", 94 | " print(f\"Average Accuracy: {svc.average_accuracy()}%\")\n", 95 | " print(f\"Misclassifications: {svc.misclassifications} out of {svc.n_iter} examples\")" 96 | ] 97 | } 98 | ], 99 | "metadata": { 100 | "interpreter": { 101 | "hash": "12c0503252f5e3b599e9b1df0980693168c0f1e59ac79299172e5f3c099bd4f7" 102 | }, 103 | "kernelspec": { 104 | "display_name": "Python 3.10.0 64-bit", 105 | "language": "python", 106 | "name": "python3" 107 | }, 108 | "language_info": { 109 | "codemirror_mode": { 110 | "name": "ipython", 111 | "version": 3 112 | }, 113 | "file_extension": ".py", 114 | "mimetype": "text/x-python", 115 | "name": "python", 116 | "nbconvert_exporter": "python", 117 | "pygments_lexer": "ipython3", 118 | "version": "3.7.11" 119 | }, 120 | "orig_nbformat": 4 121 | }, 122 | "nbformat": 4, 123 | "nbformat_minor": 2 124 | } 125 | -------------------------------------------------------------------------------- /Supervised/SVM.py: -------------------------------------------------------------------------------- 1 | import sklearn 2 | from sklearn import datasets, svm, metrics 3 | from sklearn.neighbors import KNeighborsClassifier 4 | 5 | cancer_data = datasets.load_breast_cancer() 6 | 7 | # x & y is for supervised learning 8 | x = cancer_data.data 9 | y = cancer_data.target 10 | 11 | x_train, x_test, y_train, y_test = sklearn.model_selection.train_test_split(x, y, test_size=0.2) 12 | 13 | # Classes from dataset (Cancer_data) 14 | classes = ["malignant", "benign"] 15 | 16 | # Support Vector Classifier 17 | model_svm = svm.SVC(kernel="linear", C=3) 18 | model_svm.fit(x_train, y_train) 19 | 20 | svm_prediction = model_svm.predict(x_test) 21 | svm_accuracy = str(round(metrics.accuracy_score(y_test, svm_prediction), 2) * 100) + "%" 22 | print(svm_accuracy) 23 | 24 | model_knn = KNeighborsClassifier(n_neighbors=9) 25 | model_knn.fit(x_train, y_train) 26 | 27 | knn_prediction = model_knn.predict(x_test) 28 | knn_accuracy = str(round(model_knn.score(x_test, y_test), 2) * 100) + "%" 29 | print(knn_accuracy) 30 | -------------------------------------------------------------------------------- /Supervised/Sigmoid.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 4, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%matplotlib inline\n", 10 | "\n", 11 | "import numpy as np\n", 12 | "import matplotlib.pyplot as plt" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 5, 18 | "metadata": {}, 19 | "outputs": [], 20 | "source": [ 21 | "def sigmoid(z):\n", 22 | " \"\"\" Simple Logistic Sigmoid Function \"\"\"\n", 23 | " return 1.0 / (1.0 + np.exp(-z))" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "1. Notice that $\\phi{(z)}$ approaches 1 if $z$ goes toward infinity $(z \\rarr \\infty)$ since $e^{-z}$ becomes very small for large values of z.\n", 31 | "2. Similarly, $\\phi{(z)}$ goes toward 0 for $z \\rarr -\\infty$ as a result of an increadingly large denominator.\n", 32 | "3. Therefore, we can conclude that this sigmoid function takes real-number values as input and transforms them into values in the range [0, 1] with an intercept at $\\phi{(z)} = 0.5$" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 6, 38 | "metadata": {}, 39 | "outputs": [ 40 | { 41 | "data": { 42 | "image/png": "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", 43 | "text/plain": [ 44 | "
" 45 | ] 46 | }, 47 | "metadata": { 48 | "needs_background": "light" 49 | }, 50 | "output_type": "display_data" 51 | } 52 | ], 53 | "source": [ 54 | "z = np.arange(-7, 7, 0.1)\n", 55 | "phi_z = sigmoid(z)\n", 56 | "# Plot function\n", 57 | "plt.plot(z, phi_z)\n", 58 | "plt.axvline(0.0, color=\"k\")\n", 59 | "plt.ylim(-0.1, 1.1)\n", 60 | "plt.xlabel(\"z\")\n", 61 | "plt.ylabel(\"$\\phi{z}$\")\n", 62 | "# y axis ticks and gridline\n", 63 | "plt.yticks([0.0, 0.5, 1.0])\n", 64 | "ax = plt.gca()\n", 65 | "ax.yaxis.grid(True)\n", 66 | "plt.show()" 67 | ] 68 | } 69 | ], 70 | "metadata": { 71 | "interpreter": { 72 | "hash": "1aad91322e9f4b1bca8b3144bcf5b08e5cbaa8e2651c1f57f28c5e4d868b523d" 73 | }, 74 | "kernelspec": { 75 | "display_name": "Python 3.10.0 64-bit ('ml_env': venv)", 76 | "language": "python", 77 | "name": "python3" 78 | }, 79 | "language_info": { 80 | "codemirror_mode": { 81 | "name": "ipython", 82 | "version": 3 83 | }, 84 | "file_extension": ".py", 85 | "mimetype": "text/x-python", 86 | "name": "python", 87 | "nbconvert_exporter": "python", 88 | "pygments_lexer": "ipython3", 89 | "version": "3.10.0" 90 | }, 91 | "orig_nbformat": 4 92 | }, 93 | "nbformat": 4, 94 | "nbformat_minor": 2 95 | } 96 | -------------------------------------------------------------------------------- /Unsupervised/KMeansExample.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "x, y, z = features[:3]\n", 10 | "x_n = np.vstack((x, y, z)).T\n", 11 | "\n", 12 | "kmeans = KMeans(n_clusters=3)\n", 13 | "kmeans.fit(x_n)\n", 14 | "\n", 15 | "centroids = kmeans.cluster_centers_\n", 16 | "labels = kmeans.labels_\n", 17 | "print(features)\n", 18 | "\n", 19 | "colors = (\"r.\", \"g.\", \"b.\")\n", 20 | "\n", 21 | "fix, ax = plt.subplots()\n", 22 | "\n", 23 | "for i in range(len(x_n)):\n", 24 | " ax.plot(x_n[i][0], x_n[i][1], colors[labels[i]], markersize=10)\n", 25 | "\n", 26 | "ax.scatter(centroids[:, 0], centroids[:, 1], marker=\"x\", s=150, linewidth=5, zorder=10, color=\"black\")" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "# def kmeans_test(dataset, k):\n", 36 | "# kmeans = KMeans(n_clusters=k)\n", 37 | "# kmeans.fit()\n", 38 | "# feature_count = len(dataset.data.T)\n", 39 | "# centroids = kmeans.cluster_centers_\n", 40 | "# labels = kmeans.labels_\n", 41 | " \n", 42 | "# iterations = 0\n", 43 | "# old_centroid = None\n", 44 | " \n", 45 | "# print(feature_count)\n", 46 | " \n", 47 | "# # while True:\n", 48 | "# # old_centroid = centroids\n", 49 | "# # iterations += 1\n", 50 | "\n", 51 | "\"\"\"\n", 52 | "def plot_data():\n", 53 | " a, b, c = features[:3]\n", 54 | " j = np.vstack((a, b, c)).T\n", 55 | " \n", 56 | " colors = (\"r.\", \"g.\", \"b.\")\n", 57 | " fig = plt.figure() \n", 58 | " ax = fig.add_subplot(111)\n", 59 | " plt.grid()\n", 60 | " for i in range(len(j)):\n", 61 | " ax.plot(j[i][0], j[i][1], colors[self.y[i]], markersize=10)\n", 62 | "\"\"\"" 63 | ] 64 | } 65 | ], 66 | "metadata": { 67 | "language_info": { 68 | "name": "python" 69 | }, 70 | "orig_nbformat": 4 71 | }, 72 | "nbformat": 4, 73 | "nbformat_minor": 2 74 | } 75 | -------------------------------------------------------------------------------- /Unsupervised/unsupervised.py: -------------------------------------------------------------------------------- 1 | """ Unsupervised learning """ 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | from sklearn.cluster import MeanShift 5 | from matplotlib import style 6 | from sklearn.cluster import KMeans 7 | style.use("ggplot") 8 | 9 | x = [1, 5, 1.5, 8, 1, 9] 10 | y = [2, 8, 1.8, 8, 0.6, 11] 11 | 12 | X = np.array([[1, 2], 13 | [5, 8], 14 | [1.5, 1.8], 15 | [8, 8], 16 | [1, 0.6], 17 | [9, 11]]) 18 | 19 | kmeans = KMeans(n_clusters=2) 20 | kmeans.fit(X) 21 | 22 | centroids = kmeans.cluster_centers_ 23 | labels = kmeans.labels_ 24 | 25 | print(f"Centroids: {centroids}\nLabels: {labels}") 26 | 27 | colors = ["g.", "r."] 28 | 29 | for i in range(len(X)): 30 | print(f"Coordinates: {X[i]}, Labels: {labels[i]}") 31 | plt.plot(X[i][0], X[i][1], colors[labels[i]], markersize=10) 32 | 33 | plt.scatter(centroids[:, 0], centroids[:, 1], marker="x", s=150, linewidths=5, zorder=10) 34 | plt.show() -------------------------------------------------------------------------------- /image-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytesenseidk/Machine-Learning/57386bce7e3bee8cac5bf25357552b5ce5edddb1/image-1.png -------------------------------------------------------------------------------- /image-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytesenseidk/Machine-Learning/57386bce7e3bee8cac5bf25357552b5ce5edddb1/image-2.png -------------------------------------------------------------------------------- /image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytesenseidk/Machine-Learning/57386bce7e3bee8cac5bf25357552b5ce5edddb1/image.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | absl-py==1.2.0 2 | astunparse==1.6.3 3 | cachetools==5.2.0 4 | certifi==2022.9.24 5 | charset-normalizer==2.1.1 6 | contourpy==1.0.5 7 | cycler==0.11.0 8 | flatbuffers==22.9.24 9 | fonttools==4.37.4 10 | gast==0.4.0 11 | google-auth==2.12.0 12 | google-auth-oauthlib==0.4.6 13 | google-pasta==0.2.0 14 | grpcio==1.49.1 15 | h5py==3.7.0 16 | idna==3.4 17 | keras==2.10.0 18 | Keras-Preprocessing==1.1.2 19 | kiwisolver==1.4.4 20 | libclang==14.0.6 21 | Markdown==3.4.1 22 | MarkupSafe==2.1.1 23 | matplotlib==3.6.1 24 | numpy==1.23.3 25 | oauthlib==3.2.1 26 | opt-einsum==3.3.0 27 | packaging==21.3 28 | pandas==1.5.0 29 | Pillow==9.2.0 30 | protobuf==3.19.6 31 | pyasn1==0.4.8 32 | pyasn1-modules==0.2.8 33 | pyparsing==3.0.9 34 | python-dateutil==2.8.2 35 | pytz==2022.4 36 | requests==2.28.1 37 | requests-oauthlib==1.3.1 38 | rsa==4.9 39 | six==1.16.0 40 | tensorboard==2.10.1 41 | tensorboard-data-server==0.6.1 42 | tensorboard-plugin-wit==1.8.1 43 | tensorflow==2.10.0 44 | tensorflow-estimator==2.10.0 45 | tensorflow-io-gcs-filesystem==0.27.0 46 | termcolor==2.0.1 47 | typing_extensions==4.4.0 48 | urllib3==1.26.12 49 | Werkzeug==2.2.2 50 | wrapt==1.14.1 51 | --------------------------------------------------------------------------------