Perceptron Algorithm in Linearly Non-Separable Problems

Perceptron Algorithm in Linearly Non-Separable Problems

Problem Description

​ Generate a dataset of 200 dots that is linearly non-separable.

​ Coding to prove that the perceptron algorithm cannot deal with the linearly non-separable problems directly.

Code Description

The code is accomplished in Python3.

# -*- coding : utf-8 -*- 
from numpy import *
import numpy as np
import pandas as pd
from matplotlib.colors import ListedColormap
import matplotlib.pyplot as plt
from matplotlib import rcParams
import math

def normal_distribution(x, mean, sigma):
    """
    Gauss distribution function
    
    Parameters
    ----------
        x        : the input value
        mean     : the mean of gauss distribution
        sigma    : the sigma of gauss distribution 

    Returns
    -------
        The value of x in gauss distribution 
    """
    # unlinear case
    return np.exp(-1*((x-mean)**2)/(2*(sigma**2)))/(math.sqrt(2*np.pi)*sigma)
    # linear case
    # return sigma * x / 10 + mean

def gauss_plot(mean, sigma):
    """ 
    Plot gauss distribution function
    
    Parameters
    ----------
        mean     : the mean of gauss distribution
        sigma    : the sigma of gauss distribution
    """
    x = np.linspace(mean - 6*sigma, mean + 6*sigma, 200)
    y = normal_distribution(x, mean, sigma)
    plt.plot(x, y, 'k', label ='m = {}, sigma = {}'.format(mean, sigma))
 
def generate_dataset(data_n, x_bord, y_bord):
    """
    Generate and plo the dataset
    
    Parameters
    ----------
        data_n : the size of the dataset
        x_bord : maxium of x in the dataset
        y_bord : maxium of y in the dataset

    Returns
    -------
        data_mat
    """
    x_mat = (np.random.rand(data_n,1) - 0.5) * x_bord / 0.5
    y_mat = np.random.rand(data_n,1) * y_bord
    data_mat = np.concatenate([x_mat, y_mat], 1)
    return data_mat

def dataset_classify(data_mat, mean, sigma):
    """
    Color the 2 types of dots:  
    if the dot is above the gauss line, color = 'red,
    or the color = 'blue'
    
    Parameters
    ----------
        data_mat : data_mat
        mean     : the mean of gauss distribution
        sigma    : the sigma of gauss distribution

    Returns
    -------
        Real Labels
    """
    # is_up = data_mat[:,1]>=normal_distribution(data_mat[:,0],mean,sigma)
    # rdots = data_mat[is_up]
    # bdots = data_mat[np.logical_not(is_up)]
    # plt.scatter(rdots[:,0],rdots[:,1],c = 'r')
    # plt.scatter(bdots[:,0],bdots[:,1],c = 'b')
    label = []
    for i in range(data_mat.shape[0]):
        if data_mat[i][1] >= normal_distribution(data_mat[i][0],mean,sigma):
            # plt.scatter(data_mat[i][0], data_mat[i][1], c = 'b')
            label.append(1)
        else:
            # plt.scatter(data_mat[i][0], data_mat[i][1], c = 'r')
            label.append(-1)
    return label


def show_plot():
    """ Show the plot"""
    plt.legend()
    plt.grid()
    plt.show()

class Perceptron(object):
    """Perceptron classifier.

        Parameters
        ------------
        eta : float
        Learning rate (between 0.0 and 1.0)
        n_iter : int
        Passes over the training dataset.
        random_state : int
        Random number generator seed for random weight
        initialization.

        Attributes
        -----------
        w_ : 1d-array
        Weights after fitting.
        errors_ : list
        Number of misclassifications (updates) in each epoch.
    """

    def __init__(self, eta=0.01, n_iter=50, random_state=1):
        """ Initialize """
        self.eta = eta
        self.n_iter = n_iter
        self.random_state = random_state
    
    def fit(self, X, y):
        """Fit training data.

        Parameters
        ----------
        X : {array-like}, shape = [n_samples, n_features]
            Training vectors, where n_samples is the number of
            samples and
            n_features is the number of features.
        y : array-like, shape = [n_samples]
            Target values.
        
        Returns
        -------
        self : object
        """
        rgen = np.random.RandomState(self.random_state)
        self.w_ = rgen.normal(loc=0.0, scale=0.01,
                                size=1 + X.shape[1])
        self.errors_ = []
        for _ in range(self.n_iter):
            errors = 0
            for xi, target in zip(X, y):
                update = self.eta * (target - self.predict(xi))
                self.w_[1:] += update * xi
                self.w_[0] += update
                errors += int(update != 0.0)
            self.errors_.append(errors)
        return self

    def net_input(self, X):
        """Calculate net input"""
        return np.dot(X, self.w_[1:]) + self.w_[0]
        
    def predict(self, X):
        """Return class label after unit step"""
        return np.where(self.net_input(X) >= 0.0, 1, -1)

def plot_decision_regions(X, y, classifier, resolution=0.02):

    # setup marker generator and color map
    markers = ('s', 'x', 'o', '^', 'v')
    colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
    cmap = ListedColormap(colors[:len(np.unique(y))])

    # plot the decision surface
    x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
                            np.arange(x2_min, x2_max, resolution))
    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
    Z = Z.reshape(xx1.shape)
    plt.contourf(xx1, xx2, Z, alpha=0.3, cmap=cmap)
    plt.xlim(xx1.min(), xx1.max())
    plt.ylim(xx2.min(), xx2.max())
    
    # plot class samples
    for idx, cl in enumerate(np.unique(y)):
        plt.scatter(x=X[y == cl, 0],
        y=X[y == cl, 1],
        alpha=0.8,
        c=colors[idx],
        marker=markers[idx],
        label=cl,
        edgecolor='black')


# --------------------------------------------------------
# Test
# --------------------------------------------------------

# Parameters
mean    = 0         # the mean of gauss distribution
sigma   = 2         # the sigma of gauss distribution
data_n  = 200       # the size of the dataset
x_bord  = 10        # the maxium of x in the dataset
y_bord  = 0.2       # the maxium of y in the dataset

# Generate the dataset
gauss_plot(mean, sigma)
data_mat = generate_dataset(data_n, x_bord, y_bord)
label = dataset_classify(data_mat, mean, sigma)

# Trianing 
ppn = Perceptron(0.1, 10)
ppn.fit(data_mat, label)
plot_decision_regions(data_mat, label, classifier = ppn)

# Show plot
show_plot()

Running Environment

Python 3.7.3

Experiment Results

Original Dataset

Generate 200 dots randomly. Then use the Gauss Distribution function to divide the dataset:

​ 1. If the dot is above the line, then draw in blue.

​ 2. Else, draw in red.

As a result, the dataset is Linear inseparability.

The result is shown as follows:

在这里插入图片描述

Trained Decision

Tested randomly to show that perceptron algorithm cannot deal with the linearly non-separable problems directly.

The result is shown as follows:
在这里插入图片描述

Reference

PYTHON MACHINE LEARNING By Dr. Sebastian Raschka

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值