スマレジエンジニアyushiのブログ

スマレジエンジニアのブログ

【機械学習入門 #4】Perceptron実装前半 予測ロジック

機械学習に入門しています。

yushi-dev.hatenablog.com

今回から、Perceptronを実装していきます。

設計

class Perceptron(object):
    def __init__(self):
        self.w_ = np.zeros(1 + X.shape[1])

    def predict(self, X):
        """
        1.予測
        """

    def fit(self, X, y):
        """
        2.トレーニング
        """

1.予測 では、入力された特徴量(がくの長さ、花弁の長さ)を元に、 一致する(Iris-setosa)か不一致(Iris-versicolor)かを判定します。

2.トレーニング では、データ(今回は100件)を元に、重み(self.w_)を更新していくことで、正しく予測できるようにします。

予測ロジックの実装

まず、予測のベースとなる評価値の計算ロジックです。

class Perceptron(object):
    ...
    # 総入力を計算
    def net_input(self, X):
        return np.dot(X, self.w_[1:]) + self.w_[0]

Xは特徴量です。今回で言うと、[がくの長さ、花弁の長さ]の2列です。 np.dotを利用していますが、分解するとこうです。

self.w_[0] + X[0] * self.w_[1] + X[1] * self.w_[2] + ... 

つまり、self.w_[0]は定数値、self.w_[1:]は特徴量の各列に対する重みです。

次に、予測ロジックです。

class Perceptron(object):
    ...
    def predict(self, X):
        return np.where(self.net_input(X) >= 0.0, 1, -1) 

net_inputで計算される評価値が0以上なら1(一致)、0未満なら-1(不一致)を返します。

あとがき

次回はトレーニングロジックを含む後半です。

【機械学習入門 #3】データ取得・データ整形・目標設定

前回より、機械学習に入門しています。

yushi-dev.hatenablog.com

今回は、データを用意し、そのデータをもとに目標設定していきます。

データを取得

機械学習とデータは不可分です。まずは今回利用するデータを用意します。

Machine Learning Repositoryというところで公開されているiris(アヤメ)のデータを取得します。

import pandas as pd

# iris dataをダウンロード
df = pd.read_csv(
    'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data',
    header=None
)

# 全件表示する
pd.set_option('display.max_rows', None)

print(df)

f:id:yushi0:20220417224555p:plain

データの中身は下記です。

  • 1列目: がくの長さ(cm)
  • 2列目: がくの幅(cm)
  • 3列目: 花弁の長さ(cm)
  • 4列目: 花弁の幅(cm)
  • 5列目: 名前

名前の列を見てみると、下記の3種類のアヤメのデータが混ざっていることがわかります。

  • 1〜50行目: Iris-setosa
  • 51〜100行目: Iris-versicolor
  • 101〜150行目: Iris-virginica

目標設定

今回は、Iris-setosaとIris-versicolorの行、がくの長さ・花弁の長さの列のみを利用します。 そして、がくの長さ・花弁の長さを元に、それぞれの行がIris-setosaとIris-versicolorの内どちらであるのかを判定します。

データ整形

データセットを作ります。

import numpy as np

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

# X: トレーニング変数 [がくの長さ, 花弁の長さ]の一覧
# [[5.1, 1.4], [4.9, 1.4], [4.7, 1.3], ...]
X = df.iloc[0:100, [0, 2]].values

print('y\n', y)
print('X\n', X)

f:id:yushi0:20220418003356p:plain

ここで、y=目的変数とは、Iris-setosaとIris-versicolorの内どちらであるのかを示しています。今回は、-1がIris-setosa、1がIris-versicolorです。

一方、X=トレーニング変数は、がくの長さ・花弁の長さを示しています。例えば一行目のデータの[5.1 1.4]で言うと、5.1ががくの長さ、1.4が花弁の長さです。

グラフ表示

目的変数・トレーニング変数をプロットしてみます。

"""
グラフ表示(散布図)
"""

import matplotlib.pyplot as plt

data_count = 50

plt.scatter(X[:data_count, 0], X[:data_count, 1], color='red', marker='o', label='setosa')
plt.scatter(X[50:50 + data_count, 0], X[50:50 + data_count, 1], color='blue', marker='x', label='versicolor')
plt.xlabel('sepal length [cm]')
plt.ylabel('petal length [cm]')
plt.legend(loc='upper left')
plt.show()

f:id:yushi0:20220418004355p:plain

図の意味は下記の通りです。

  • x軸: がくの長さ
  • y軸: 花弁の長さ
  • 赤点: Iris-setosa
  • バツ: Iris-versicolor

赤点(Iris-setosa)と青バツ(Iris-versicolor)は座標上ではっきり位置が別れています。

つまり、 がくの長さと花弁の長さを見れば、それがIris-setosa・Iris-versicolorの内どちらであるかが分類できるということ、すなわち設定した目標が達成できそうということが、推測できます。

あとがき

今回の記事では、機械学習によってどんなことができるか(What)が表現できているんじゃないかと思います。

次回以降では、どうやって実現するか(How)を記載していこうと思います。

【機械学習入門 #2】環境構築

前回より、機械学習に入門しています。

yushi-dev.hatenablog.com

今回は、環境を構築していきます。

pyenv

pythonの複数バージョンを簡単に切り替えられるように、pyenvを導入します。

GitHub - pyenv/pyenv: Simple Python version management

導入手順は、公式ドキュメントの通りです。

https://github.com/pyenv/pyenv#installation

ライブラリ

pythonでは、pipコマンドによって様々なライブラリを導入して利用できます。

phpのcomposer、node.jsのnpmに近いものです。

今回の開発では、下記のようなライブラリを利用します。

(導入手順は後述します)

jupyter notebook

jupyter.org

ブラウザで表示するIDEのようなライブラリです。

numpy

numpy.org

数値計算を簡単・高速にするライブラリです。

matplotlib

matplotlib.org

グラフ描画用のライブラリです。

pandas

pandas.pydata.org

表計算用のライブラリです。

すごくざっくり言うと、Excel的な操作をプログラミング的に解決するようなものです。

今回はCSVからのデータ読み出しやデータ整形で使います。

anaconda

前章で紹介したライブラリを一括で導入できる仕組みです。

www.anaconda.com

pyenvから簡単に導入できます。

# pyenvでインストール可能なバージョン一覧を表示する
pyenv install -l

# anacondaの最新版を導入する
pyenv install anaconda3-2021.05

# defaultで利用するpythonを、anacondaに変更する
# 環境ごとに切り替えたい場合は、`pyenv local`を利用すること
pyenv global anaconda3-2021.05

notebookの起動

実際に環境を触ってみます。

# jupyterを起動する
jupyter notebook

ブラウザにて、下記のような画面が表示されます。

f:id:yushi0:20220404025357p:plain

notebookを作成します。新規 > Python3をクリックします。

f:id:yushi0:20220404025447p:plain

動かしてみる

試しに、グラフを描画してみます。

  • セル1つ目
# ライブラリの導入
import matplotlib.pyplot as plt
  • セル2つ目
# データ作成
x = range(1, 10)
y = [_x ** 2 for _x in x]

for _x, _y in zip(x, y):
    print(_x, _y)
  • セル3つ目
# グラフを描画する
plt.plot(x, y)

こんな感じになったでしょうか?

f:id:yushi0:20220404030443p:plain

まとめ

pythonやデータ処理を自由に行える環境が、簡単に構築できました。

【機械学習入門 #1】機械学習に入門してみる

今回から、機械学習に入門してみようと思います。

Webエンジニアと機械学習

私はWebエンジニアなので、普段機械学習の知識や技術を扱うことは、今のところ直接的にも間接的にもありません。

しかしながら、AI・機械学習といった分野はITの文脈かどうかに関わらずあらゆるところで名前を見かけますし、一過性のブームというよりは、着実に浸透しいく類のものに見えます。

Web開発の企業においても、AIエンジニア・機械学習エンジニアの募集を見かけることが増えてきています。
(実際スマレジでも常時募集を行なっています。)

今後ますます機械学習開発が進めば、(また現在でもそれが進んでいる会社では、)Webエンジニアも何らかの形でAI・機械学習技術と連携した開発が増えていくんじゃないかと予想しています。 専門にするわけではないにしても、Webエンジニアが機械学習分野について多少でも理解を持っておくことは、今後のエンジニア人生において損がないんじゃないかなと考えています。

本ブログでも、機械学習を専門に学ぶのではなくて、エンジニアとしての前提知識を活かしながら、機械学習について入門していきたいと考えています。

目標

下記の書籍を通して勉強しました。

https://www.amazon.co.jp/dp/B08LYWFPQ9/ref=cm_sw_r_tw_dp_K3WEWWJQF57F6T7CQ1K7

※ リンクは第3版ですが、今回参照したのは第1版

書籍の序盤では、Perceptronという機械学習アルゴリズムを実際に実装し、実際にデータの分類まで体験することができます。

今回は、このPerceptronの実装や動作確認を目標にして進めていこうと思います。

開発言語

機械学習において特によく利用される言語は、C/C++Pythonの2つなのかなと思います。

C/C++は非常に高速なので、機械学習のロジック自体を実装したりされます。

Pythonは記述の手軽さのために採用されていて、C/C++で実装されたライブラリを利用した実運用のためのコードの記述に利用されます。

今回は書籍に倣ってPythonで環境を作ります。

あとがき

環境構築や実装は、次回より行なっていこうと思います。

【プロフィールページ改修 第8回】ヘッダーナビゲーションのモーダル化とスムーススクロール

引き続き、プロフィールページを作成していきます。

yushi-dev.hatenablog.com

技術スタックは下記の通りです。

  • nuxt.js
  • SCSS
  • Tailwind CSS

今回はヘッダーナビゲーションの改善を行います。

ヘッダーナビゲーションのモーダル化

前回Responsive対応を行なったので、今回はヘッダーナビゲーションもスマートフォン向けに改善します。

完成イメージは下記の通りです。

f:id:yushi0:20220306234036p:plain

バツ印にはアニメーションをつけます。

f:id:yushi0:20220306235650g:plain

  • template
  <div
    class="nav-modal flex justify-center items-center"
    :class="navClass"
    @click="$emit('close')"
  >
    <ul class="ul flex flex-col justify-between">
      <li v-for="link in links" :key="link.label">
        <a @click="$emit('jump', link.href)">{{ link.label }}</a>
      </li>
    </ul>
  </div>
.nav-modal {
  position: fixed;
  height: 100%;
  width: 100%;
  z-index: 9000;
  background-color: rgba(255, 255, 255, 0.9);
  transition: all 0.5s;
  opacity: 0;
  pointer-events: none;

  &.show {
    opacity: 1;
    pointer-events: auto;
    transition: all 0.5s;
  }
  * {
    font-size: 30px;
  }
  a {
    cursor: pointer;
    text-decoration: none;
  }
}
.ul {
  height: 40%;
}

ヘッダー固定化

ヘッダーを固定化して、ページのどの位置からでも好きな位置に移動できるようにします。

下記のようなイメージです。

f:id:yushi0:20220307001759g:plain

ヘッダー固定化自体は単にposition: fixed;と指定してます。

工夫しているのは、メインイメージを通り過ぎた後は、ヘッダーの背景色を緑にしているところです。
色は、メインイメージからスポイトで取り出して設定しています。

  mounted() {
    window.addEventListener('scroll', () => {
      const header = document.querySelector('.hero-image')
      this.isScrolled = window.scrollY > header.clientHeight - 50
    })
  },
.header {
  z-index: 8000;
  .header-wrap {
    & > * {
      transition: 1s;
    }
  }
  &.scrolled {
    .header-wrap {
      & > * {
        background-color: $main-1;
      }
    }
  }
}

スムーススクロール

ヘッダーナビゲーションのリンク移動を、スクロールで行う機能を実装しました。

下記のようなイメージです。

f:id:yushi0:20220307002729g:plain

    scrollLink(href) {
      const target = document.querySelector(href)
      const top = target.offsetTop - 30;
      window.scrollTo({
        top,
        behavior: 'smooth',
      })
    },

下記のページを参考にさせていただきました。

スムーススクロールとは?jQuery・CSS・JavaScriptそれぞれでの使用方法について詳しく解説! | .NETコラム

Pull Request

https://github.com/nek0meshi/profile/pull/10

https://github.com/nek0meshi/profile/pull/11

まとめ

細かな修正ですが、こういうところが揃うとかなり雰囲気が良くなるなと思いました。

【プロフィールページ改修 第7回】Responsive対応

引き続き、プロフィールページを作成していきます。

yushi-dev.hatenablog.com

技術スタックは下記の通りです。

  • nuxt.js
  • SCSS
  • Tailwind CSS

今回はResponsive対応を行います。

media query

各sectionを.app-containerというクラスで囲います。

<section class="app-container>
  <h2>ABOUT</h2>
  <div>...</div>
</section>

.app-containerのstyleを実装します。

$mobile-max-width: 768px;
$tablet-max-width: 1024px;

.app-container {
  width: $tablet-max-width;
  margin-left: auto;
  margin-right: auto;
  padding-left: 15px;
  padding-right: 15px;
  @media (max-width: $tablet-max-width) {
    width: $mobile-max-width;
  }
  @media (max-width: $mobile-max-width) {
    width: 100%;
  }
}

スマートフォンタブレット・PCの3段階で区切り、media query(@media (...))を利用して切り替えます。

スマートフォンでは、幅は100% - padding(15px)とします。
タブレットとPCでは、それぞれ幅を定数で固定します。

flexbox

スキルやリンクなどのカード表示は、あらかじめflexboxで実装していました。

幅に合わせて柔軟に列数が変わり、自動的に折り返します。

画面

f:id:yushi0:20220220222717p:plain

f:id:yushi0:20220220222752p:plain

  • PC

f:id:yushi0:20220220222803p:plain

Pull Request

https://github.com/nek0meshi/profile/pull/9

まとめ

ここまでやると一旦表に出せる感じがします。

【プロフィールページ改修 第6回】デザイン改善

引き続き、プロフィールページを作成していきます。

yushi-dev.hatenablog.com

技術スタックは下記の通りです。

  • nuxt.js
  • SCSS
  • Tailwind CSS

今回はデザイン改善を進めていきます。

方針

前回まででざっとコーディングとコンテンツ入力を行いました。
今回は見栄えをいい感じに整えていきます。

表示時のアニメーション

表示の瞬間に、下からふわっと浮き上がりながらフェードインするアニメーションを実装しました。

f:id:yushi0:20220206220647g:plain

@keyframes fadein {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
.skill-card-fade-in {
  opacity: 0;
  &.show {
    animation: fadein 0.5s .1s ease-in forwards;
  }
}

hover時のアニメーション

hover時に、手前に浮き上がってくるアニメーションを実装しました。

f:id:yushi0:20220206220528g:plain

.card-wrap {
  transition: 0.5s;
  &:hover {
    box-shadow: 0 0 50px -10px $gray-2;
    transition: 0.5s;
  }
}

hover時のアニメーション2

hover時に、上に浮き上がるアニメーションを実装しました。

f:id:yushi0:20220206220411g:plain

.link-logo {
  transition: 0.5s;
  &:hover {
    transition: 0.5s;
    transform: translateY(-5px);
  }
}

Pull Request

https://github.com/nek0meshi/profile/pull/6 https://github.com/nek0meshi/profile/pull/7 https://github.com/nek0meshi/profile/pull/8

まとめ

普段アニメーションの実装をすることがあまりなかったので、とても勉強になりました。