心音データの解析をしながら、以下のことを学んでいきます。
# ここはコードセルです。
"全国医療AIコンテスト"
s = input("あなたの名前を入れてください→ ")
print(s," は全国医療AIコンテストに参加しています")
a = 123
b = -23
sample_string = "Artificial Intelligence"
print(12 + 3,
"\n", # 改行を出力するときは \n を入力します。(\ はバックスラッシュと言ってパソコンの機種で打ち方が変わるので、調べましょう。)
4 * 4,
"\n",
12 / 5,
"\n",
12 / 5.0,
"\n",
12 % 5,
"\n",
5 ** 3,
"\n",
a + b,
"\n",
"What is " + sample_string,
"\n",
str(a) + sample_string) # 文字列に変換するときは、str()が使えます。
if 条件式A:
条件式Aが真であるときに実行したい処理
elif 条件式B:
条件式Aが偽で,条件式Bが真であるときに実行したい処理
elif 条件式C:
...
else:
全ての条件が偽であるときに実行したい処理
pressure = input("血圧をいれてください。") # 出力セルで数値を入力したい時は input() が使えます
#inputで入るのは文字列なのでint()で囲うこと数字に変換する↓
pressure = int(pressure)
if pressure >= 140:
print("あなたは高血圧です")
elif pressure >=130:
print("あなたは高値血圧です")
else:
print("あなたは正常血圧です")
even_list = [2, 4, 6, 8, 10]
string_list = ["abc", "def", "hello", "world"]
[n]
を付けて表します。ここで、要素番号は0から始まるので、左から数えて4番目の要素のインデックスは になります。even_list[3] # 8が出力される
string_list[0] # "abc"が出力される
list_of_list = [[1, 2, 3], [2, 3, 4], [5, 6, 7, 8]]
list_of_list[0] # [1, 2, 3]が出力される
list_of_list[1][2] # 4が出力される
for ループ変数 in リスト:
繰り返したい処理
muscle = "sternocleidmastoid" #変数muscleにsternocleidmastoidを代入
for i in range(5):
print(muscle)
def 関数名():
処理
関数名()
def curry():
print('カレーを作ります')
print('↓')
print('まず肉を炒めます')
print('↓')
print('その後野菜をいためます。')
print('↓')
print('ルーを入れて煮込むと完成です。')
print('↓')
print('肉と野菜のカレーの完成です')
curry()
def 関数名(引数名):
処理
return 戻り値
x = 関数名(引数)
def add(a, b):
curry()
return a + b
add(4, 8)
12
heartbeat
というディレクトリをデフォルトのディレクトリ /content
の下に作成し、そこに関連データをダウンロードしています。コマンドとはコンピュータに計算やファイルの操作を行うように指示できるツールです。今回は詳しく触れませんが、colabのようなノートブックではpythonとコマンドを混ぜて使えるのが一つの強みです。
# ! を先頭につけると一時的に適応される。例えばワーキングディレクトリの移動をしてもその後のコマンドには適応されない。
# heartbeat ディレクトリを作成します。
!mkdir heartbeat
# % を先頭につけると永続的に適応される。ワーキングディレクトリの移動をしてもその後も適応される。
# heartbeat ディレクトリに移動します。
%cd heartbeat
# S1とS2の位置が記録されているデータのダウンロード
!wget http://www.peterjbentley.com/heartchallenge/Atraining_normal_seg.csv
# 正常心音データのダウンロード(zipの中身はaifファイル)
!wget http://www.peterjbentley.com/heartchallenge/Atraining_normal.zip
!unzip Atraining_normal.zip
!ls
%cd ..
/content/heartbeat
--2021-05-18 04:24:23-- http://www.peterjbentley.com/heartchallenge/Atraining_normal_seg.csv
Resolving www.peterjbentley.com (www.peterjbentley.com)... 209.151.22.160
Connecting to www.peterjbentley.com (www.peterjbentley.com)|209.151.22.160|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3412 (3.3K) [text/csv]
Saving to: ‘Atraining_normal_seg.csv’
Atraining_normal_se 100%[===================>] 3.33K --.-KB/s in 0s
2021-05-18 04:24:23 (432 MB/s) - ‘Atraining_normal_seg.csv’ saved [3412/3412]
--2021-05-18 04:24:23-- http://www.peterjbentley.com/heartchallenge/Atraining_normal.zip
Resolving www.peterjbentley.com (www.peterjbentley.com)... 209.151.22.160
Connecting to www.peterjbentley.com (www.peterjbentley.com)|209.151.22.160|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 13876165 (13M) [application/zip]
Saving to: ‘Atraining_normal.zip’
Atraining_normal.zi 100%[===================>] 13.23M 6.31MB/s in 2.1s
2021-05-18 04:24:26 (6.31 MB/s) - ‘Atraining_normal.zip’ saved [13876165/13876165]
Archive: Atraining_normal.zip
creating: Atraining_normal/
inflating: Atraining_normal/.DS_Store
creating: __MACOSX/
creating: __MACOSX/Atraining_normal/
inflating: __MACOSX/Atraining_normal/._.DS_Store
inflating: Atraining_normal/201101070538.aif
inflating: __MACOSX/Atraining_normal/._201101070538.aif
inflating: Atraining_normal/201101151127.aif
inflating: __MACOSX/Atraining_normal/._201101151127.aif
inflating: Atraining_normal/201102081152.aif
inflating: __MACOSX/Atraining_normal/._201102081152.aif
inflating: Atraining_normal/201102081321.aif
inflating: __MACOSX/Atraining_normal/._201102081321.aif
inflating: Atraining_normal/201102201230.aif
inflating: __MACOSX/Atraining_normal/._201102201230.aif
inflating: Atraining_normal/201102260502.aif
inflating: __MACOSX/Atraining_normal/._201102260502.aif
inflating: Atraining_normal/201102270940.aif
inflating: __MACOSX/Atraining_normal/._201102270940.aif
inflating: Atraining_normal/201103090635.aif
inflating: __MACOSX/Atraining_normal/._201103090635.aif
inflating: Atraining_normal/201103101140.aif
inflating: __MACOSX/Atraining_normal/._201103101140.aif
inflating: Atraining_normal/201103140132.aif
inflating: __MACOSX/Atraining_normal/._201103140132.aif
inflating: Atraining_normal/201103140135.aif
inflating: __MACOSX/Atraining_normal/._201103140135.aif
inflating: Atraining_normal/201103140822.aif
inflating: __MACOSX/Atraining_normal/._201103140822.aif
inflating: Atraining_normal/201103151912.aif
inflating: __MACOSX/Atraining_normal/._201103151912.aif
inflating: Atraining_normal/201103170121.aif
inflating: __MACOSX/Atraining_normal/._201103170121.aif
inflating: Atraining_normal/201103221214.aif
inflating: __MACOSX/Atraining_normal/._201103221214.aif
inflating: Atraining_normal/201104122156.aif
inflating: __MACOSX/Atraining_normal/._201104122156.aif
inflating: Atraining_normal/201104141251.aif
inflating: __MACOSX/Atraining_normal/._201104141251.aif
inflating: Atraining_normal/201105011626.aif
inflating: __MACOSX/Atraining_normal/._201105011626.aif
inflating: Atraining_normal/201105021654.aif
inflating: __MACOSX/Atraining_normal/._201105021654.aif
inflating: Atraining_normal/201105021804.aif
inflating: __MACOSX/Atraining_normal/._201105021804.aif
inflating: Atraining_normal/201105151450.aif
inflating: __MACOSX/Atraining_normal/._201105151450.aif
inflating: Atraining_normal/201106111136.aif
inflating: __MACOSX/Atraining_normal/._201106111136.aif
inflating: Atraining_normal/201106141148.aif
inflating: __MACOSX/Atraining_normal/._201106141148.aif
inflating: Atraining_normal/201106151236.aif
inflating: __MACOSX/Atraining_normal/._201106151236.aif
inflating: Atraining_normal/201106210943.aif
inflating: __MACOSX/Atraining_normal/._201106210943.aif
inflating: Atraining_normal/201106221418.aif
inflating: __MACOSX/Atraining_normal/._201106221418.aif
inflating: Atraining_normal/201106221450.aif
inflating: __MACOSX/Atraining_normal/._201106221450.aif
inflating: Atraining_normal/201108011112.aif
inflating: __MACOSX/Atraining_normal/._201108011112.aif
inflating: Atraining_normal/201108011114.aif
inflating: __MACOSX/Atraining_normal/._201108011114.aif
inflating: Atraining_normal/201108011115.aif
inflating: __MACOSX/Atraining_normal/._201108011115.aif
inflating: Atraining_normal/201108011118.aif
inflating: __MACOSX/Atraining_normal/._201108011118.aif
Atraining_normal Atraining_normal_seg.csv Atraining_normal.zip __MACOSX
/content
import モジュール名 as モジュールを代入する変数名
pandas
というモジュールを使っていきましょう。pd
としてimportします。
pd.read_csv(ファイル名)
でデータを読み込めます。import pandas as pd
csv_path = "/content/heartbeat/Atraining_normal_seg.csv"
df = pd.read_csv(csv_path) # DataFrame の頭文字をとってよく変数名に df が使われます。
df.head()
で先頭の5行をみることができます。df.head()
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
df.shape
でデータのサイズをみることができます。df.shape
df[列の名前]
あるいはdf.列の名前
で取り出せます。列が全部取ってこられるので、特定の行を取り出したい時はそのインデックスを指定する必要があります。Unnamed: 0
という列のインデックスが1
の要素の中身をみてみましょう。index = 1
FILE = df["Unnamed: 0"][index]
FILE
Unnamed: 0
に書かれています。cols = df.columns.values # .valuesでデータフレームの中身の値をとってこれる
s1cols = [col for col in cols if col[:2] == "S1" ] # 最初の2文字がS1の列名を格納
s2cols = [col for col in cols if col[:2] == "S2" ] # 最初の2文字がS2の列名を格納
s1data = df.loc[index,s1cols].values # データフレーム.values で中身の値の配列が返される
s2data = df.loc[index,s2cols].values
print(s1data, "\n", s2data)
FILE
にどのようなデータが入っているのかみてみましょう。aif
というファイル形式を扱うので、それに特化した aifc
というモジュールを使用します。今回のように知らないモジュールを使う場面に沢山出くわしますが、全ての使い方を覚えなければいけないというわけではありません。知らない人でも使えるように、モジュールを作った人たちが使い方の解説を書いてくれています。色んなサイトで使い方の記事がありますが、基本的には公式のドキュメントが一番正確です。今回の aifc
というモジュールはPythonにもともと入っている標準ライブラリで、こちらのPython公式ドキュメントに使い方が書いてあるので、参考にしながら使ってみます。pandas
で抽出したデータの保存先ファイル名から読み込んでどんなデータなのかみてみましょう。import aifc
PATH = "/content/heartbeat/Atraining_normal/" + FILE # ファイル名だけでなく、ファイルの場所を指定する必要がある(パス)
f = aifc.open(PATH,"rb")
params = f.getparams()
params
オーディオファイルには、オーディオデータについて記述したパラメータがたくさん含まれています。サンプリングレートあるいはフレームレートは、1秒あたりのオーディオサンプル数です。チャンネル数は、モノラル、ステレオ、4チャンネルかどうかを示します。フレームはそれぞれ、チャンネルごとに一つのサンプルからなります。サンプルサイズは、一つのサンプルの大きさをバイト数で示したものです。したがって、一つのフレームはnchannels * samplesize
バイト からなり、1秒間ではnchannels * samplesize * framerate
バイトで構成されます。
params
で返されたメタ情報から今回の音声ファイルはチャンネル数 = 1 (モノラル)
サンプルサイズ = 2 [byte]
サンプリングレート = 44100 [Hz]
1 * 2 = 2 [byte]
、1秒間では 1 * 2 * 44100 = 88200 [byte]
であることがわかります。nframes = f.getnframes()
framerate = f.getframerate()
T = nframes / framerate
T
frames = f.readframes(nframes) # 抽出するフレーム数を指定する
print(type(frames))
type(object)
でみることができます。フレームデータはバイト型であることがわかりました。f.close()
np
でimportします。import numpy as np
np.array(リスト)
a = np.array([1, 2, 4])
a
matrix = np.array([[1, 2, 3], [2, 3, 4], [3, 4, 5]])
matrix
vector = np.array([[1], [2], [3]])
vector
matrix.shape
+
記号でベクトル同士の和を表現できたり、*
記号で定数倍を表現できます。vector_2 = np.array([[2], [5], [6]])
vector + vector_2
3 * vector
matrix @ vector
実は行列演算に特化している点とは別にNumpyを使う大きなメリットがあります。それは実行時間 です。Numpyの内部ではC言語によって記述されていて、また行列演算にはBLAS APIという高性能の行列演算ライブラリを用いているのでPythonとは比べ物にならないくらい高速となります。
np.frombuffer(bytes file, dtype = "型を指定")
で変換することができます。2 [byte] = 16 [bit]
なのでファイル規格から dtype = "int16"
を指定することも大事です。データの構造も知っている必要はなくて、わからなかったことは調べたら出てきます。data = np.frombuffer(frames, dtype="int16")
data
s1data
s1data = s1data.astype(np.int32)
ValueError Traceback (most recent call last)
<ipython-input-29-77bdc267fed2> in <module>()
----> 1 s1data = s1data.astype(np.int32)
ValueError: cannot convert float NaN to integer
s1data = s1data.astype(np.float32)
s2data = s2data.astype(np.float32)
print(s1data, "\n", s2data)
nan
以外の値だけ抽出しましょう。s1data = s1data[~np.isnan(s1data)]
s2data = s2data[~np.isnan(s2data)]
print(s1data,"\n",s2data)
s1frame = s1data.astype(np.int32)
s2frame = s2data.astype(np.int32)
print(s1frame,"\n",s2frame)
pyplot.機能名
で提供されています。慣例的にimport matplotlib.pyplot as plt
でimportし、plt.機能名
でさまざまな描画機能を使えるようにします。%matplotlib inline
は、Notebook上にグラフを表示するためのマジックコマンドです。忘れやすいので、注意しましょう。import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(x, y)
を使います。100個の点を図示したかったらそれぞれのx座標とy座標の配列を入れてあげます。配列の形式はリストでもnumpy配列でもどちらでも大丈夫です。scale = 1000 / framerate # 44100 Hz で記録しているので、間隔は 1000 / 44100 ms
# データ点のx座標の配列を指定
x = np.arange(0, T*1000, scale)
# グラフの大きさを指定
plt.figure(figsize=(20, 10))
# plt.plot(x, y)
plt.plot(x, data)
# x軸の名前を指定
plt.xlabel("ms")
# グラフのタイトルを指定
plt.title("Heartbeat (Index: {})".format(index))
# 図を表示
plt.show()
# データ点のx座標の配列を指定
# S1, S2 それぞれの座標を指定
# グラフの大きさを指定
# plt.plot(x, y)
# S1とS2を散布図でマーキング
# 各線や点の説明を表示する
# x軸の名前を指定
# グラフのタイトルを指定
# 図を表示
def displayHb(index):
# index に対応するファイル名の取得
# ファイルのパスを指定して開く
# フレーム数・フレームレート・記録時間を取得
# 全フレームのデータを取得
# フレームデータを int16 型 のnumpy配列に変換
# メモリのスケールを指定 [ms]
# データ点のx座標の配列を指定
# グラフの大きさを指定
# plt.plot(x, y)
# x軸の名前を指定
# グラフのタイトルを指定
# 図を表示
# test
# indexが[3, 5, 8, 10, 16]のいずれかはファイルが開けないのでそれ以外
index = 2
displayHb(index)
def displayHbWithS1S2(index):
# s1, s2のフレーム位置を取得
# s1, s2のフレーム位置配列をそれぞれ nan を除いた int32 型 のnumpy配列に変換
# index に対応するファイル名の取得
# ファイルのパスを指定して開く
# フレーム数・フレームレート・記録時間を取得
# 全フレームのデータを取得
# フレームデータを int16 型 のnumpy配列に変換
# メモリのスケールを指定 [ms]
# データ点のx座標の配列を指定
# S1, S2 それぞれの座標を指定
# グラフの大きさを指定
# plt.plot(x, y)
# S1とS2を散布図でマーキング
# 各線や点の説明を表示する
# x軸の名前を指定
# グラフのタイトルを指定
# 図を表示
# test
# indexが[3, 5, 8, 10, 16]のいずれかはファイルが開けないのでそれ以外
index = 2
displayHbWithS1S2(index)