머신러닝

1-12 Pandas 라이브러리에 의한 데이터 입출력

coding art 2020. 1. 29. 17:37
728x90

Iris flowers 데이터를 대상으로 Pandas 라이브러리의 기본 사용법을 알아보자.




pd.read_csv Pandas 라이브러리 지원하에 웹 URL 주소에서 CSV 파일을 읽어 들이는 명령 사례이다. CSV 파일은 숫자와 콤마 또는 세미콜론과 같은 구분문자(delimiter)로 이루어지는 엑셀에서 준비 가능하지만 엑셀 포맷이 아닌 텍스트형 데이터 파일로서 광법위하게 사용되므로 반드시 그 사용법을 익혀야 한다.


(Shell)에서 읽어 들인 CSV 파일을 직접 출력해 보면 읽은 후 delimiter 는 제거되었으며 header=None 으로 상단에 라벨 값 대신 숫자가 입력되었으며 왼쪽 첫 번째 열에서는 인덱스 넘버가 추가되어 있다.



.iloc 명령 처리에 의한 결과를 5개 출력해 보자. 그림과 같이 지정된 개수만큼의 데이터 출력을 확인할 수 있다.






한편 이 데이터를 직접 머신 러닝에 사용할 수는 없으므로 NumPy에서 지원하는 어레이(array) 형태로 바꾸어 사용하도록 한다.

df.iloc[0:100, 4].vaules 명령을 실행하면 0번부터 99번까지에 해당하는 총 4(column)의 데이터가 어레이로 변환한다. (Shell)에서 출력하여 확인해 보도록 하자.





다음은 첨부된 코드를 실행하여 Iris flowers 데이터를 읽어서 Scikit-learn에서 지원하는 Adaline-Stochastic Gradient Descent 루틴으로 학습시키는 과정에서 matplotlib 라이브러리를 사용하여 출력한 그래픽 처리 결과이다.


참고로 앞에 기술한 내용은 Pandas 라이브러리의 대표적인 사용법을 설명하기 위함이며 첨부된 코드의 구체적인 내용 설명은 필자의 저서를 참조해 보기 바란다.


#Iris_Adaline_SGD.py

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap

df = pd.read_csv('https://archive.ics.uci.edu/ml/'
        'machine-learning-databases/iris/iris.data', header=None)
df.tail()
df = pd.read_csv('iris.data', header=None)
df.tail()

#select setosa and versicolor
y = df.iloc[0:100, 4].values
y = np.where(y == 'Iris-setosa', -1, 1)

#extract sepal length and petal length
X = df.iloc[0:100, [0, 2]].values

#standardize features
X_std = np.copy(X)
X_std[:, 0] = (X[:, 0] - X[:, 0].mean()) / X[:, 0].std()
X_std[:, 1] = (X[:, 1] - X[:, 1].mean()) / X[:, 1].std()


#Large scale machine learning and stochastic gradient descent

class AdalineSGD(object):
    """ADAptive LInear NEuron classifier.

    Parameters
    ------------
    eta : float
      Learning rate (between 0.0 and 1.0)
    n_iter : int
      Passes over the training dataset.
    shuffle : bool (default: True)
      Shuffles training data every epoch if True to prevent cycles.
    random_state : int
      Random number generator seed for random weight
      initialization.


    Attributes
    -----------
    w_ : 1d-array
      Weights after fitting.
    cost_ : list
      Sum-of-squares cost function value averaged over all
      training samples in each epoch.

       
    """
    def __init__(self, eta=0.01, n_iter=10, shuffle=False, random_state=None):
        self.eta = eta
        self.n_iter = n_iter
        self.w_initialized = False
        self.shuffle = shuffle
        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

        """
        self._initialize_weights(X.shape[1])
        self.cost_ = []
        for i in range(self.n_iter):
            if self.shuffle:
                X, y = self._shuffle(X, y)
            cost = []
            for xi, target in zip(X, y):
                cost.append(self._update_weights(xi, target))
            avg_cost = sum(cost) / len(y)
            self.cost_.append(avg_cost)
        return self

    def partial_fit(self, X, y):
        """Fit training data without reinitializing the weights"""
        if not self.w_initialized:
            self._initialize_weights(X.shape[1])
        if y.ravel().shape[0] > 1:
            for xi, target in zip(X, y):
                self._update_weights(xi, target)
        else:
            self._update_weights(X, y)
        return self

    def _shuffle(self, X, y):
        """Shuffle training data"""
        r = self.rgen.permutation(len(y))
        return X[r], y[r]
   
    def _initialize_weights(self, m):
        """Initialize weights to small random numbers"""
        self.rgen = np.random.RandomState(self.random_state)
        self.w_ = self.rgen.normal(loc=0.0, scale=0.01, size=1 + m)
        self.w_initialized = True
       
    def _update_weights(self, xi, target):
        """Apply Adaline learning rule to update the weights"""
        #output means hypothesis
        output = self.activation(self.net_input(xi))
        error = (target - output)
        self.w_[1:] += self.eta * xi.dot(error)
        self.w_[0] += self.eta * error
        cost = 0.5 * error**2
        return cost
   
    def net_input(self, X):
        """Calculate net input"""
        return np.dot(X, self.w_[1:]) + self.w_[0]

    def activation(self, X):
        """Compute linear activation"""
        return X

    def predict(self, X):
        """Return class label after unit step"""
        return np.where(self.activation(self.net_input(X)) >= 0.0, 1, -1)

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

    #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')


ada = AdalineSGD(n_iter=15, eta=0.01, random_state=1)
ada.fit(X_std, y)

plot_decision_regions(X_std, y, classifier=ada)
plt.title('Adaline - Stochastic Gradient Descent')
plt.xlabel('sepal length [standardized]')
plt.ylabel('petal length [standardized]')
plt.legend(loc='upper left')

plt.tight_layout()
plt.show()

plt.plot(range(1, len(ada.cost_) + 1), ada.cost_, marker='o')
plt.xlabel('Epochs')
plt.ylabel('Average Cost')

plt.tight_layout()
plt.show()
ada.partial_fit(X_std[0, :], y[0])