旅行好きなソフトエンジニアの備忘録

プログラミングや技術関連のメモを始めました

【Python】 OpenCVのモジュールをインポートすると"ImportError: DLL not found."というエラーが出る

Visual Studioをインストールしていない)Windows7/Anaconda4.2.0 for Python3.5という環境で
conda install –channel https://conda.anaconda.org/menpo opencv3
を実行してopencv3をインストールしたのですが、import cv2のところで"ImportError: DLL not found.“というエラーが出ました。その後、

  1. Visual Studio 2013 Professionalをインストール
  2. opencv3をアンインストール
  3. opencv3を再度インストール

という手順を踏むことで"ImportError: DLL not found.“というエラーが出なくなりました。環境の違いはVisual Studioの有無のみですが、ここ(python - Can't import cv2; "DLL load failed" - Stack Overflow)で書かれているようにVisual C++ Redistributable Packageと関係があるのかもしれません。

【Python】 区切り文字を複数指定して文字列を分割する

C#のSplitメソッドと異なりPythonのSplitメソッドは区切り文字を一つしか指定できないようです。区切り文字を複数指定したい場合はreモジュールを利用する必要があります。

import re
str = 'a,b.c_d-e'
re.split('[,._-]', str) # ['a', 'b', 'c', 'd', 'e']と出力される

【Python】 pipでconnect timeoutが発生する

会社でpipをするとタイムアウトに。。。単純にプロキシの問題で、こちらの情報(pythonメモ proxy下でのpip、easy_install - Qiita)に助けていただきました。

pip install pycrypto –proxy=user@proxy.hoge.jp:port

【Python】 特異スペクトル解析法の実装

特異スペクトル解析法をPythonで実装したのでメモします。書籍「信号解析 馬杉著」からの引用ですが、

特異スペクトル解析法(singular spectrum analysis)は、観測信号からの主要な変動成分の分離・抽出、観測信号の変化点や不規則点の検出、観測信号からの雑音除去などを目的として、非線形信号解析分野において発展した解析手法の一つである。フーリエ級数展開やウェーブレット級数展開のように、特定の基底関数を適用したり、あるいは、ARモデルのような特定のモデルを仮定せずに、信号の構造変化そのものを解析するため、非定常信号の分離に向いている。

これをSingularSpectrumAnalysisクラスとしてpythonで実装します。

import numpy as np

class SingularSpectrumAnalysis(object):
    """特異スペクトル解析法を行うクラス"""
    
    def __init__(self, signal, window_size):
        """
        コンストラクタ
        @param signal 解析対象信号
        @param window_size 部分時系列区間数
        """
        self.__signal_length = len(signal)
        self.__window_size = window_size
        X = self.__create_trajectory_matrix(signal, window_size)
        self.__U, self.__W, self.__V = np.linalg.svd(X, False)

    def __create_trajectory_matrix(self, signal, window_size):
        """
        軌道行列を生成するメソッド
        @param signal 解析対象信号
        @param window_size 部分時系列区間数
        @return 軌道行列
        """
        row = len(signal) - window_size + 1
        col = window_size
        trajectory_matrix = np.empty((row, col))
        for i in range(row):
            trajectory_matrix[i, :] = signal[i:i + window_size]
        return trajectory_matrix

    def restore_signal(self, num_component):
        """
        信号を復元するメソッド
        @param num_component 軌道行列を近似する項数
        @return 復元された信号
        """
        # 軌道行列を復元する
        X = np.zeros((self.__U.shape[0], self.__window_size))
        for i in range(num_component):
            lambda_ = self.__W[i]
            U = (self.__U[:,i])[:, np.newaxis]
            V = (self.__V[i,:])[np.newaxis, :]
            X += lambda_*U*V
        
        # 軌道行列から信号を復元する
        signal = []
        for i in range(self.__signal_length):
            value = 0.0
            count = 0
            for j in range(X.shape[1]):
                row = i - j
                if (row < 0):
                    break
                elif (row >= X.shape[0]):
                    continue
                col = j
                value += X[row, col]
                count += 1
            value /= count
            signal.append(value)
        return np.array(signal)

軌道行列から信号を復元する部分に関して、numpyでfor文を使うのはコードの見た目やパフォーマンス上良くないようなのですが、綺麗に実装する方法が分かりませんでした。次にSingularSpectrumAnalysisクラスを利用する例を見てみます。解析する信号を下図に示します。
f:id:ni4muraano:20170131155032j:plain
この信号は下図に示す三種類の信号を混ぜた信号です。基本トレンドは直線で、直線にsin波とノイズを合わせました。f:id:ni4muraano:20170131155136j:plain
以下はこの信号をSingularSpectrumAnalysisクラスで解析する例です。

import numpy as np
np.random.seed(1) # 常に同じノイズを生成する
import matplotlib.pyplot as plt
from SingularSpectrumAnalysis import SingularSpectrumAnalysis

# 信号の生成
x = np.arange(100)
signal1 = x/10
signal2 = np.random.rand(len(x))/2
signal3 = np.sin(x/2)
signal = signal1 + signal2 + signal3
# 特異スペクトル解析の実施
window_size = 20
ssa = SingularSpectrumAnalysis(signal, window_size)
num_component = 1
restored_signal = ssa.restore_signal(num_component)

plt.hold(True)
plt.title("num_component=" + str(num_component))
plt.plot(signal)
plt.plot(restored_signal)
plt.show()

上記のnum_componentを1から4まで変えて結果をプロットします。
f:id:ni4muraano:20170131155650j:plain:w280f:id:ni4muraano:20170131155655j:plain:w280f:id:ni4muraano:20170131155700j:plain:w280f:id:ni4muraano:20170131155706j:plain:w280 num_component=1の時は基本トレンドの直線らしき信号が復元されています。num_componentの数字を上げるにしたがって元の信号に近くなっており、num_component=4で直線とsin波を合わせたような信号が復元されています。

信号解析-信号処理とデータ分析の基礎

信号解析-信号処理とデータ分析の基礎

【Python】 KerasのConv2Dの引数paddingについて

KerasのConv2Dを使う時にpaddingという引数があり、'valid'と'same'が選択できるのですが、これが何なのかを調べるとStackExchangeに書いてありました(convnet - border_mode for convolutional layers in keras - Data Science Stack Exchange)。

'valid'

出力画像は入力画像よりもサイズが小さくなる。
f:id:ni4muraano:20170129144610j:plain

'same'

ゼロパディングすることで、出力画像は入力画像と同じサイズになる。
f:id:ni4muraano:20170129145937j:plain

ゼロパディングすることのメリットについてはここ(定番のConvolutional Neural Networkをゼロから理解する - DeepAge)に書いてあります。

  • 端のデータに対する畳み込み回数が増えるので端の特徴も考慮されるようになる
  • 畳み込み演算の回数が増えるのでパラメーターの更新が多く実行される
  • カーネルのサイズや、層の数を調整できる

【Python】 KerasでXOR回路を作成する

Kerasを使ってXOR回路を作成するというのは実用性はありませんが、自分がKeras初心者のため「とにかく簡単なサンプルが欲しい」と思い作成しました。まず、XOR回路は下記のようになります。
f:id:ni4muraano:20170127114534j:plain
ここでは入力に対して出力が下記表のようになるよう、図中のwの値を調整します。

x_1 x_2 y
0 0 0
1 0 1
0 1 1
1 1 0

これをKerasを使ってプログラムを書くと以下のコードとなります(コメントを日本語で書くとエラーが出たため、英語でコメントを書きました)。

# -*- coding: utf-8 -*-
import numpy as np

from keras.models import Sequential, model_from_json
from keras.layers.core import Dense
from keras.optimizers import RMSprop

# Input data
X_train = np.array([[0.0, 0.0],
                    [1.0, 0.0],
                    [0.0, 1.0],
                    [1.0, 1.0]])
# Teacher for input
Y_train = np.array([0.0,
                    1.0,
                    1.0,
                    0.0])

# Build model
model = Sequential()
output_count_layer0 = 2
model.add(Dense(output_count_layer0, input_shape=(2,), bias=True, activation='sigmoid')) # Need to specify input shape for input layer
output_count_layer1 = 1
model.add(Dense(output_count_layer1, bias=True, activation='linear'))
model.compile(loss='mean_squared_error', optimizer=RMSprop(), metrics=['accuracy'])

# Start training
BATCH_SIZE = 4
ITERATION = 3000
history = model.fit(X_train, Y_train, batch_size=BATCH_SIZE, nb_epoch=ITERATION, verbose=0)

# Evaluate model
X_test = X_train
Y_test = Y_train
score = model.evaluate(X_test, Y_test, verbose=0)
print('Test score:', score[0])
print('Test accuracy:', score[1])

# Save model
model_file_name = 'xor.json'
model_json = model.to_json()
with open(model_file_name, 'w') as file:
    file.write(model_json)
# Save weights
weight_file_name = 'xor_weights.hdf5'
model.save_weights(weight_file_name)

# Load model
with open(model_file_name, 'r') as file:
    model_json = file.read()
    model = model_from_json(model_json)
# Load weights
model.load_weights(weight_file_name)

# Predict using trained model
y = model.predict(np.array([[0, 0]]))

とても短いコードで記述することが出来ました。Kerasはこれから少しずつ勉強したいと思います。