Kuzunoha-NEのブログ

プログラミングなどの勉強をしてます

【kubernetes】SecretとRedisのパスワード設定

こんばんは、葛の葉です。

さて、今回はkubernetesでRedisをデプロイする際のパスワードの設定とSecretの設定方法を記載します。

環境

minikube ver 0.31.0

Redis(image) tag 5.0.3

簡単なRedisのパスワード設定のおさらい

Redisがインストールされている環境であれば、以下のコマンドでパスワードを設定できます。

redis-server --requirepass [password]

コマンドを打つとRedisが起動して、以下のような感じでメッセージが出力されると思います。今回のパスワードは1212です。

root@657cb0734634:/data# redis-server --requirepass 1212
15:C 20 Feb 2019 04:05:48.917 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
15:C 20 Feb 2019 04:05:48.918 # Redis version=5.0.3, bits=64, commit=00000000, modified=0, pid=15, just started
15:C 20 Feb 2019 04:05:48.918 # Configuration loaded
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 5.0.3 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 15
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

15:M 20 Feb 2019 04:05:48.919 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
15:M 20 Feb 2019 04:05:48.920 # Server initialized
15:M 20 Feb 2019 04:05:48.920 * DB loaded from disk: 0.000 seconds
15:M 20 Feb 2019 04:05:48.920 * Ready to accept connections

パスワードが設定されれば、そのRedisに接続したあと、操作を行うにはパスワードが必要になります。例えばredis-cliで接続した際は、auth [password]といった形で認証を得ないといけません。

root@657cb0734634:/data# redis-cli -h 192.168.99.100 -p 6379 
192.168.99.100:6379 > auth 1111
ERR invalid password
192.168.99.100:6379 > auth 1212
OK

ERR invalid passwordと出るとパスワードが間違っています。OKが出てれば接続できます。ここまでがRedisでパスワードを設定する方法とそのRedisに繋げる方法です。

redis.io

KubernetesのSecret

さて、KubernetesのSecretですが、詳細は以下のリンクを見てもらえればと思います。

kubernetes.io

KubernetesではこのSecretというオブジェクトを使ってパスワードを管理したほうが良いようです。先ほどの1212というパスワードを管理するSecretを作成します。

ファイル名test-secret.yaml

apiVersion: v1
kind: Secret
metadata:
    name: redis-password # secretの名称となり、k8s上で使用する名前
type: Opaque
data:
    RedisPassword: MTIxMg== #base64でないと受け付けません。

metadatanameを使って、このSecretをredis-password命名し、Kubernetes内ではこの名前でこのSecretを呼び出します。また、data内にあるRedisPasswordMTIxMg==はKeyとValueになっています。MTIxMg==base641212になります。Keyは複数作ることが出来ますので、一つのSecretに複数のパスワード等を含めることが出来ます。例えばusernamekeyとpasswordkeyを入れるなんてことも出来ます。

kubectl apply -f test-secret.yamlとすれば設定が反映されます。

kubectl get secretとすればSecretが表示されます。

NAME                       TYPE                                  DATA      AGE
default-token-57h4x        kubernetes.io/service-account-token   3         5d
redis-password             Opaque                                1         28m

default-token-57h4xはminikubeのものかなぁと。

Podの設定はこんな感じ

次にKubernetes上でRedisの入ったPodを作成します。今回はSecretの設定はPodで行いますが、DeployMentやStatefulSetでも設定可能です。

ファイル名test-pod.yaml

apiVersion: v1  
kind: Pod
metadata:
  name: test-redis
  labels:
    app: test-redis #ここの値を用いてServiceと連携する
spec:
  containers:
  - name: test-redis-ctr
    image: redis:5.0.3
    env:
    - name: REDIS_PASSWORD # Pod内に挿入する環境変数の名前
      valueFrom:
        secretKeyRef: 
          name: redis-password # 先ほど作成したSecret名
          key: RedisPassword #  先ほど作成したKey名。Valueが環境変数内に代入される。
    command: ["redis-server"]
    args: ["--requirepass $(REDIS_PASSWORD)"]
    ports:
    - containerPort: 6379

yaml内のspec以下にcontainers項目があって、これらが生成するコンテナの詳細に設定する部分になります。-nameはコンテナの名前です。imageはそのPodを作成するに使用するDockerimageを記します。

また、envがあって、これがPod内の環境変数を作成する項目になります。env-name環境変数名です。 valueFromはその環境変数の値を引っ張ってくる設定ファイルがどの形式であるかというもので、Secretを使用する場合はsecretKeyRefとします。configMapKeyRefだとConfigMapというオブジェクトを使用するようになります。nameはSecretの名前を、keyはSecret内dataで記入したkeyであるRedisPasswordにします。

commandはPod生成時に実行されるコマンドで、redis-serverというコマンドを、argsで引数を渡しています。--requirepassは先に説明したとおりで、$(REDIS_PASSWORD)環境変数部分になります。ブランケットの括弧${}ではなくパレンティスの括弧$()なので注意してください。

kubectl apply -f test-pod.yamlで作成しましょう。

kubectl get podsで出来たPodを見られます。

NAME                              READY     STATUS      RESTARTS   AGE
test-redis                        1/1       Running     0          34m

なお、STATUSがErrImagePullといったものであった場合は、Redis:5.0.3のイメージが存在していないので作成できていないというエラーになります。minikubeでしたらdocker pull redis:5.0.3とかやってみてください。

Serviceを使ってみる(minikube)

次にServiceを使って先のPodを確認出来るようにします。

ファイル名test-svc.yaml

apiVersion: v1 # ここも固定。kubernetes側が対応したらVの値を増やす形に
kind: Service metadata:
  name: test-service # Serviceそのものの名前。アンスコが使えない等ルールあり
spec:
  type: NodePort  
  selector:
    app: test-redis 
  ports:
  - port: 6379 
    targetPort: 6379 

Serviceの説明は省きます。kubectl apply -f test-svc.yamlで作成し、kubectl get service (又は"svc")と打って確認しましょう。

NAME                    TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
test-service            NodePort       10.111.68.208   <none>        6379:30271/TCP   38m

CLUSTER-IPPORT(S)のコロン右側の値はそれぞれ異なると思います。

IPアドレスとポート番号を確認する

GKEと違って、minikubeではNodePortタイプ(LoadBalancerタイプも同様)のServiceにEXTERNAL-IPは振られないようです。代わりに、minikubeの下記のコマンドでIPアドレスを確認する必要があります。

minikube service [Service名] --url

kubernetes.io

今回はminikube service test-service --urlです。そうしますと、http://192.168.99.100:30271といった表示が出てくると思います。IPアドレス部分、Port番号部分はそれぞれ異なると思います。

C:\>minikube service test-service --url
http://192.168.99.100:30271

これが今回生成したServiceにアクセスするためのIPアドレスとPort番号になります。

redis-cliでアクセス

下記コマンドを打ちます。

redis-cli -h [IPアドレス] -p [Port番号]

root@kuzunohasan:# redis-cli -h 192.168.99.100 -p 30271
192.168.99.100:30271> get 1
(error) NOAUTH Authentication required.
192.168.99.100:30271> auth 1212
OK
192.168.99.100:30271> get 1
(nil)

最初のget 1(error) NOAUTH Authentication required.と弾かれていますが、auth 1212とした後、get 1とした場合は(nil)とされています。無事成功しています。

綺麗にする

kubectl apply -f ***.yamlで設定したものはkubectl delete -f ***.yamlで削除可能です。

また、applyでもそうですが、ディレクトリを選択すれば、ディレクトリ内のyamlファイル全てを読みに行き、全てを削除してくれます。

C:\>kubectl delete -f test-secret.yaml
secret "redis-password" deleted

C:\>kubectl delete -f test-pod.yaml
pod "test-redis" deleted

C:\>kubectl delete -f test-svc.yaml
service "test-service" deleted

なんでRedisConfでパスワードの設定しないの?

今回のRedisのパスワードの設定はサーバー実行コマンドのオプションを使っていて、confを使った設定は行っていません。なぜならconf内で環境変数を呼び出して取得する方法がなかったからです…シェルスクリプトを使ったらよいかもしれませんね。

github.com

【Python】 値が文字列の中に含まれているか確認する。

こんばんは、葛の葉です。

さて、標題の件になりますが、ちょっと言葉だと説明しにくいかなと思います。例を挙げると

I Have a Dream.

Wikipediaより引用

ja.wikipedia.org

この中に特定の文字が入っていないかをBoolで返してもらう方法を書きます。

inを使う

例えばaという単語が入っているかを確認するには以下のようにします。

 'a' in 'I Have a Dream'

以下がコマンドラインPythonを実行したときの結果です。

>>> 'a' in 'I Have a Dream'
True
>>> 'b' in 'I Have a Dream'
False

Boolで返るのでassertも使えます。

>>> assert 'a' in 'I Have a Dream'
>>> assert 'b' in 'I Have a Dream'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

assert 'a' in 'I Have a Dream'は特に問題がないためTrueとなり、エラーなどは発生していません。一方、assert 'b' in 'I Have a Dream'はFalseとなるため、AssertionErrorとなっています。

listに入った複数の文字列が該当の文字列内に含まれているかの確認

例えば以下のように、IHaveaの文字全てが該当の文字列に含まれているかを確認したいとします。しかし、下記のようにリストをinとしてもTypeErrorが返されます。

>>> ['I', 'Have', 'a'] in 'I Have a Dream'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'in <string>' requires string as left operand, not list

リスト内包表記を使う

というわけでリスト内包表記を使いましょう。

False not in [i in 文字列 for i in 検索したい文字列の入ったリスト]

コマンドラインでは以下のようになります。

>>> False not in [i in 'I Have a Dream' for i in ['I', 'Have', 'a']]
True

分解するとFalse not in [リスト][i in 'I Have a Dream' for i in ['I', 'Have', 'a']]になると思います。

False not in [リスト]は最初にお話した'a' in 'I Have a Dream'の応用で、[list]の中にFalseが無ければTrueとなります。すなわち、リスト内が全てTrueだとTrueを返し、一つでもFalseがあればFalseを返します。ヤヤコシイネ。

>>> False not in [True,True,True,True]
True
>>> False not in [True,True,True,False]
False
>>> False not in [False,False,False,False]
False

さて、[i in 'I Have a Dream' for i in ['I', 'Have', 'a']]ですが、こちらは下部と同じ結果になります。

return_list = []
for i in ['I', 'Have', 'a']:
    result = i in 'I Have a Dream'
    return_list.append(result)

return_lisrt
[True, True, True]

結果は[True, True, True]となります。

すなわち、for文を用いて、含まれているか確認したい文字列が入ったリストの要素を一つずつとりだし、それぞれinを用いてBool値を返してもらい、それをリストの中に格納しています。

リスト内包表記での結果はこちら。

[i in 'I Have a Dream' for i in ['I', 'Have', 'a']]
[True, True, True]

含まれていない文字があればFalseがリストに返されます。

>>> [i in 'I Have a Dream' for i in ['I', 'king', 'a']]
[True, False, True] # kingの文字は存在しない

上記のFalse not inと組み合わせると

>>> False not in [i in 'I Have a Dream' for i in ['I', 'Have', 'a']]
True
>>> False not in [i in 'I Have a Dream' for i in ['I', 'king', 'a']]
False

と、このようになるわけです。

assertではこうです。

>>> assert False not in [i in 'I Have a Dream' for i in ['I', 'Have', 'a']]
>>> assert False not in [i in 'I Have a Dream' for i in ['I', 'king', 'a']]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

関数はこちら

def bool_check_words_in_word(check_words: list, the_word: str):
    # check_wordsには確認したい文字が含まれているリストを入れてください。
    # the_wordにはチェックしたい文字列を入れてください。
    return False not in [check_word in the_word for check_word in check_words]
print(
    bool_check_words_in_word(
        check_words=['I', 'Have', 'a'],
        the_word='I Have a Dream')
)

True

【Docker】docker-compose "exec" について

こんばんは、葛の葉です。

さて、DockerComposeを使ってコンテナを立ち上げたり、あるいはDockerNetworkを構築したりすることがあると思います。DockerComposeで立ち上げたコンテナの中に侵入するためにdocker exec -it コンテナ名 /bin/bashと打つ方もいらっしゃるかと思いますが、docker-compose.ymlにコンテナ名を確認しに行ったり、docker ps -a等で動いている(あるいは死んでる)コンテナを見に行ったりしてコンテナ名を確認したりしているのかなと思慮します。

前置きが長くなってしまいましたが、今回は上記よりもう少し簡単にDockerComposeで起動したコンテナ内に侵入できるdocker-compose execについてお話します。

docker-composeの記載内容の例

version: "3"
services:
    py:
        build: .
        image: python:3.6.5
        container_name: test_python
        volumes:
          - "./program/:/var/program/"
        tty: true
        networks:
            test_net:
                ipv4_address: 172.20.0.2
    rdy:
        image: redis:4.0.10
        container_name: test_redis
        volumes:
          - "./data:/data"
        networks:
            test_net:
                ipv4_address: 172.20.0.3
networks:
    test_net:
        driver: bridge
        ipam:
            driver: default 
            config: 
            - subnet: 172.20.0.0/24 

上記のようなdocker-compose.ymlがあったとします。今回の方法ではサービスを用います。DockerComposeにおけるサービスとはコンテナにオプションを施したものの単位という認識でよいと思います。今回、docker-compose.ymlに記載されているサービスはpyrdyとになります。pyというサービスはpython:3.6.5のイメージを使ってコンテナを作成し、volumesというオプションを使ってホストとゲスト間のディレクトリを共有しています。

まず、docker-compose.ymlがあるディレクトリ上でdocker-compose up -dコマンドを実行し、2つのサービスをデタッチドモード起動しましょう。2つのサービスの起動が完了するまで待ちます。

上記のサービスに侵入するには以下のコマンドを使用します。

docker-compose exec (service名) /bin/bash

今回のケースだとdocker-compose exec py /bin/bashになります。

root@50947e77690d:/#

こんな感じで出力されたかと思います。50947e77690dの部分は人やタイミングによって変わるかな、と思います。

docker-compose exec (service名) (command)

例えばdocker-compose exec py pythonとすることで、Pythonコマンドラインを出力することできます。

Python 3.6.5 (default, Jun 27 2018, 08:15:56)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.

今回は起動したサービスの元となっているImageがpython:3.6.5であり、pythonがインストールされているイメージであるため、上記のコマンドラインが出現しています。

では、もう一つのサービスであるrdyのコンテナに入ってみましょう。こちらはRedis:4.0.1がインストールされているサービスなります。

> docker-compose exec rdy redis-cli set testkey hoge
OK
> docker-compose exec rdy redis-cli get testkey
"hoge"

docker-compose exec rdy redis-cli set testkey hogeを分解すると

docker-compose exec はDockerComposeのコマンド

rdydocker-compose.ymlで作成したサービスの名前

redis-cli set testkey hogeはサービスに実行してもらうコマンド部分になります。

余談ですが、redis-cliコマンドはRedis用のコマンドです。set (KEY) (VALUE)とすると、KEYに値をセットでき、get (KEY)とするとKEYにセットされた値を出力しています。

今回はtestkeyというKEYにhogeというVALUEを与えています。

/bin/bashもコマンドです

ご存知の方が多いと思いますが、/bin/bashbashというshellを呼び出すコマンドです。docker-compose exec (service名) /bin/bashとは、サービス内のbashを呼び出しているので、サービス内に侵入できているわけです。

【Python】byte型だけが入ったlistを全てstr型に変換したlistとして返す + アノテーションを少し

こんばんは、葛の葉です。

さて、私は最近、Redisを使っているのですが、Pythonを通して取得した場合、byte型で受け取ることになると思います。Listとして受け取った場合、List内全てがbyte型になってしまいます。今回はbyteが入ったリストを一括で変化するための関数を作りました。

環境

Python 3.6.5

コード

def byte_to_str(byte_list: list) -> list:
    return [i.decode('utf8') for i in byte_list]

少し変わった書き方が見えると思います。引数(byte_list: list) -> list: list-> listアノテーションと言って、注釈の意味になります。(byte_list: list)の個所のアノテーションは「引数に入れるのはリストで入れてください」と注釈しています。また、 -> listの個所は返り値の型がlistであることを注釈しています。ただ、あくまで注釈なので拘束力はありません。

もう一つ、返り値の[i.decode('utf8') for i in byte_list]の書き方はリスト内包表記となっております。

実行

test_list = [b'python',b'ruby', b'node', b'golang']
byte_to_str(test_list)
['python', 'ruby', 'node', 'golang']

さもありなん

アノテーションあれこれ

文字列を入れることもできるので説明しやすくていいですね。

def byte_to_str(byte_list: "byteだけが入ったlistを入れてね") -> "listで返します。":
    return [i.decode('utf8') for i in byte_list]

また、アノテーションには拘束力はないので、引数に文字列を入れることが出来てしまいます。以下は引数を文字列で渡しました。結果、strオブジェクトのAttributeErrorになっています。引数として読み込まれたtest変数が関数内で.decode('utf8')を呼び出そうとした際に起きたErrorです。str.decode('utf8')インスタンスが無いのでAttributeErrorとなります。

test = 'insert str'
byte_to_str(test)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in byte_to_str
  File "<stdin>", line 2, in <listcomp>
AttributeError: 'str' object has no attribute 'decode'

その他、アノテーションについて、詳しくはPEPの以下のリンクをチェック

www.python.org

【Python】 インスタンス変数を辞書型で出力 + JSON形式で文字列にする。

こんばんは、葛の葉です。

Pythonインスタンス変数を辞書型で出力する方法とそれをJSONに変換する方法を記載します。

環境

Python 3.6.5

こんな感じ

class MyClass(object):
    def __init__(self, name):
        self.name = name
        self.gender = 'male'
        self._address = '192-1999'
        self.interest = ['Kemono Friends', 'DoDonpachi', 'Python']
        self.age = 111

myclass = MyClass('kuzunoha')

このようにクラスとインスタンスを作成する。

print(myclass.__dict__)

myclass.__dict__インスタンス変数を辞書型として持っている。

{'name': 'kuzunoha', 'gender': 'male', '_address': '192-1999', 'interest': ['Kemono Friends', 'DoDonpachi', 'Python'], 'age': 111}

JSON形式文字列にする。

内部modulejsonjson.dumpsを使ってJSON型にする。

import json # ここ追加になっている点に注意

class MyClass(object):
    def __init__(self, name):
        self.name = name
        self.gender = 'male'
        self._address = '192-1999'
        self.interest = ['Kemono Friends', 'DoDonpachi', 'Python']
        self.age = 111

    def to_json(self):
        return json.dumps(self.__dict__, ensure_ascii=False, indent=4) 

myclass = MyClass('kuzunoha')

json.dumps(self.__dict__, ensure_ascii=False, indent=4)jsonモジュールを使って辞書型をjsonに変更しています。

オプションのensure_ascii=Falseはこれを打たないとバイト文字になってしまうので、そのようにしています。

indent=4はインデントを空白4つで自動で行ってくれます。自動ってすごい。かしこい。

print(myclass.to_json())で出力してみましょう。

{
    "name": "kuzunoha",
    "gender": "male",
    "_address": "192-1999",
    "interest": [
        "Kemono Friends",
        "DoDonpachi",
        "Python"
    ],
    "age": 111
}

上記の通り出ている。けれども、少し問題なのがアンダースコア_で定義したインスタンス変数もそのまま出力されている点かも?

それが嫌なら、一度、インスタンス変数の辞書をコピーして、そこから_addressを抜き取ってみる?

    def to_json(self):
        dicts = self.__dict__.copy()
        # 以下の要素はjsonには要らないので削除
        dicts.pop('_address')

        return json.dumps(dicts, ensure_ascii=False, indent=4)
myclass = MyClass('kuzunoha')

print(myclass.to_json())

{
    "name": "kuzunoha",
    "gender": "male",
    "interest": [
        "Kemono Friends",
        "DoDonpachi",
        "Python"
    ],
    "age": 111
}

【Docker】Windowsで「curl」コマンド使いたい件について[byrnedo/alpine-curl]

お世話になっております。葛の葉です。

WindowsPowerShellにはInvoke-WebRequestというLinuxBASHでいうところのcurlみたいなコマンドがついていて、何かHTTP系に色んなテストをしてみたいときなんかは有効です。しかし、curlに慣れていたりするとコマンドが打ちにくい、結果もなんだかわかりにくい等、curlがやっぱり使いたい、ってときがあります。

そんなときに便利なDockerImageがbyrnedo/alpine-curlです。

hub.docker.com

使い方は書いてある通り

先のURLにも書いてありますが…まぁ書いておきます。

docker pull byrnedo/alpine-curl

先ず、DockerImageをダウンロードするため、上記のコマンドを打ちます。-tオプションでタグを指定するのもよいと思いますが、まぁ気にしなくてもいいかなぁと思います。ダウンロードが終われば使用可能です。

docker run --rm byrnedo/alpine-curl (url)

このコマンドでHTTPのrequestを確認することができます。

なお、dockerの--rmオプションは、コンテナを通してコマンドを実行し、そのコマンドが完了したときにそのコンテナを消す、というオプションになります。curlコマンドは何回も使うはずなので、そのたびにコンテナのカスが溜まっていくことを防いでいるわけですね。

docker run --rm byrnedo/alpine-curl https://www.google.co.jp

Googleのサイトをcurlで受け取ればソースコードを取得できます。あとはcurlの操作そのまま使えるので調べて使ってみてみてくださいな。

なお、Win版のcurlもある模様

下記URLにあります。一番下のほうにWindows64bit用のリンクがあるので、それを落としてbinフォルダ以下に環境変数PATHを通してあげましょう。PowerShellではcurlコマンドがInvoke-WebRequestにaliasされているので、curl.exeってコマンドになるか、あれこれ設定をしてあげなきゃあいけません。詳しくはググってもらったほうがいいかな。

curl.haxx.se

参考

qiita.com

【Python】Scikitlearnの内LinearRegressionを使った値予測を行う

こんばんは、葛の葉です。機械学習ライブラリであるsklearnを使ってデータの学習と予測…と言いたいところなんだけど、なんだかいいデータがなくて、全く無造作なデータを学習させて予測するという意味のないことやってました。

環境

Anaconda 5.3.0

Python 3.7.0

numpy 1.15.1

pandas 0.23.4

jupyter 1.0.0

scikit-learn 0.19.2

適当なデータを使う。

tekito.csv

data1,data2,data3
22,62,73
22,66,61
76,58,26
35,60,43
35,30,100
61,35,97
50,62,48
87,94,86
95,33,34
35,58,32
79,84,20
82,15,92
50,66,37
62,89,74
53,51,65
74,80,75
89,27,80
100,62,78
97,77,79
88,37,54

data1,data2,data3は共に15から100の数値を適当出力する設定にしているだけなので、なんも意味を持ちません。

重回帰分析を使う

回帰分析のうち、目的変数に対して説明変数が2つ以上のものを重回帰分析といい、説明変数が1つの場合は単回帰分析と言うみたいです。

目的変数とは予測したいデータで今回はdata3です。

説明変数とは目的変数を予測するために使うデータのことdata1,data2です。

data1data2を使ってdata3を予測するというのが今回の目的です。

回帰分析については以下のWikipediaも参照。

回帰分析 - Wikipedia

説明変数のデータ

test.csv

data1,data2
35,77
60,43
45,53
64,65
81,21
90,33
100,46
50,18
30,32
29,60

このtest.csvdata1,data2を使ってdata3に相当するデータを出力する。

JupyterNoteBookを使う

以下はJupyterNoteBook上でのコマンドになります。

ライブラリのインポート

import pandas as pd
import numpy as np # 要らないかも
from sklearn.linear_model import LinearRegression as LR

上記コードをセルに挿入してからShift + Enterすると次のセルに移ります。

その時に何らかのエラーが出ればそれはライブラリのインポートが失敗していると思います。

from sklearn.linear_model import LinearRegression as LR

これが機械学習のライブラリsklearnです。

LinearRegressionは線形回帰を意味しているようです。

as LRとしてLinearRegressionLRとして略称します。

CSVのインポート

pandasでcsvをロードします。

train = pd.read_csv('tekito.csv')
test = pd.read_csv('test.csv')

pandas.read_csv('***.csv')はpandasのライブラリとしてcsvをpandasのDataFrameとして読み込みます。

Shift + Enterで、次のセルへ。

エラーを吐く場合は事前に説明していたCSVが、同じディレクトリ内にないとか、その辺りだとおもいます。

train.head()

.head()は読み込んだDataFrameの最初の5行分を出力します。

data1    data2   data3
0   22  62  73
1   22  66  61
2   76  58  26
3   35  60  43
4   35  30  100

Shift + Enterで、次のセルへ。

特定のカラムのデータを読み取る

trainX = train[['data1', 'data2']]
y = train['data3']
testX = test[['data1','data2']]

train内の2つのカラムを代入しています。

train[['data1', 'data2']]

yは目的変数としtrain['data3']を代入しています。

testXは最終的に予測するための説明変数をもっています。

trainXyを使ってdata1,data2data3で線形回帰を行い、最終的にはtestX内にあるdata1,data2を元にtestXのdata3に当たるデータを出力します。

Shift + Enterで、次のセルへ。

モデルの作成とモデルへの学習

model = LR()
model.fit(trainX, y)

model.fit(trainX, y).fit(説明変数, 目的変数)となっており、回帰モデルとなっています。

trainXdata1data2をもっているので重回帰モデルとなっています。

Shift + Enterで、次のセルへ。

学習したデータを出力する

pred = model.predict(testX)
pred

以下のデータが学習で出したデータになります。

array([55.80356749, 65.91988259, 62.42089327, 60.75553676, 72.7960059 ,70.4459384 , 67.91714972, 71.41497867, 66.58486472, 59.5950097 ])

さっぱり意味がないデータですけどね。

Shift + Enterで、次のセルへ。

ついでにCSVとして出力しましょう。

tester = pd.DataFrame()
tester[0] = pred
tester.to_csv('cho_tekitou.csv', header=None, index=None)

.to_csv関数にてcho_tekitou.csvという名前で出力します。

ここまできていて言うのもなんだが

data1data2は無造作なデータで、当然、法則性なんてないです。なので、最終的なpredの値はとても意味のないものになるはずです。

またpredが正確にデータを予言できているかどうか、というのも保証できません。

とりあえず、データを出せてよかったねってレベルで今回は終わりです。

f:id:Kuzunoha-NE:20190104222556p:plain