Watson Studio上のnotebookからIBM Cloud Object Storage(ICOS)へのFileの読み書き - project-libを使う -

Notebookでコードを書く際、データをファイル経由でロードするのはごく頻繁にあるケースです。ローカルのPC上でjupyter Notebookを動かしている場合は、普通のpythonのお作法で読み書きすれば問題ないですのですが、Watson StudioのNotebook上では恒久的にファイルを読み書きする場合は、一般的にはProjectに紐ついたIBM Cloud Object Storage(以下ICOS)に対してファイルの読み書きをします。

方法はいくつかあります。ICOSはAWS S3互換のオブジェクトストレージなので、AWS S3と同様の方法も使えます。またWatson StudioのNotebookのGUIから`Insert pandas DataFrames`や`Insert StreamingBody object`を使ってコード生成する方法もあります。あとはWatson StudioのNotebook専用となりますが、割と簡単に書ける`project-lib`を使う方法があります。

ここではこの方法の1つ、`project-lib`を使った方法を説明します。その他の方法は結構Qiita内でも記事になっていますので、容易に見つかると思います。

また、ICOSを使用しない別の方法としてlinuxのコマンドを直接Notebookから実行する方法もあります。他のサーバーかファイルをwget取得、他のサーバーへwputでファイルを保存する方法もあります。こちらはファイルをwget/wputできるサーバーがあることが前提となりますので、ここでは説明しません。

尚ここに書いてある情報はWatson Studioのドキュメント「[Using project-lib for Python](https://dataplatform.cloud.ibm.com/docs/content/wsj/analyze-data/project-lib-python.html)」の情報を元にしています。

[2022/02/23　Watson　Studio新画面に一部更新]

#0. 前提はWatson StudioのProjectが作成済みであること
前提は既にWatson StudioのProjectが作成済みであることです。もしまだ作成済みでなく、方法がわからない場合は

* [Watson Studio サービスとProjectの作成](https://qiita.com/nishikyon/items/ba698b638300848b746e)

を参考にまずプロジェクトを作成してから以下を開始してください。

#1. Projectを開く
作成済みProjectを開いてください。

方法がわからない場合は
[ログイン後、作成済Projectの表示方法]
(https://qiita.com/nishikyon/items/ba698b638300848b746e#4-%E3%81%8A%E3%81%BE%E3%81%91%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E5%BE%8C%E4%BD%9C%E6%88%90%E6%B8%88project%E3%81%AE%E8%A1%A8%E7%A4%BA%E6%96%B9%E6%B3%95)を参考にして開いてください。

#2. 前準備`アクセス・トークン`の作成
`project-lib`を使うには、関連付けされたICOSを含むプロジェクトの環境にアクセスできる`アクセス・トークン`を最初に作成しておく必要があります。
これは一度プロジェクトに対して作成してあればよいです。

2-1: 上部メニューから「管理」をクリックし、左側のメニューから「アクセス制御」を選択します・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/127e8696-c0c7-c38d-37c7-588532e1bddc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/758b62e5-b695-3138-7b4a-23f18b675faf.png)



2-2: 「アクセス・トークン」のタブをクリックします。右側に表示された「新規トークン+」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/389a1fb4-ff95-0270-717f-f379d8e730f6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/a70c5973-3b53-01f0-17d6-935e2d8e929c.png)



2-3: 「アクセス・トークンの追加」のウィンドウが表示されますので、「名前」と「アクセス・ロール」を設定し、「作成」または「Create」をクリックします。

- 名前: 適当にわかりやすい名前(半角で)
- アクセス・ロールの選択:　状況に応じて以下を選択します。
    - 読み込みだけの場合は「ビューアー」または「Viewer」
    - 読み込みおよび書き込みもしたい場合は「エディター」または「Editor」

この記事では読み込みおよび書き込み方法を説明しますので、「エディター」を設定した状態に設定しました。
アクセス・トークンの追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/9a015774-298a-ed42-78bb-64fbc6d703d7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/83672e40-91b4-ee83-65a4-99ed1daf0768.png)


「アクセス・トークン」に設定したトークンが表示されているのを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/e72262bb-a3ed-679d-3a04-58fc38b42365.png)


これで`project-lib`を使うNotebook外での準備が完了しました。

#3: Notebookを開く
既にファイルを読み書きしたいNotebookがあればそれを開いてください。
新たに作ってもよいです。作り方が不明の場合は
[Watson StudioでJupyter Notebookを使おう! -3. Notebookの作成-](https://qiita.com/nishikyon/items/6c5bc873e2ac7f1e5fb7#3-notebook%E3%81%AE%E4%BD%9C%E6%88%90)を参照して作成してください。

#4: 読み込ませたいファイルをICOSにアップロード
最初にも説明しましたが、`Watson StudioのNotebook上では恒久的にファイルを読み書きする場合は、一般的にはProjectに紐ついたIBM Cloud Object Storage(以下ICOS)に対してファイルの読み書きをします。` よって何かしらローカル環境(PC)にファイルがある場合は、ICOSにまずファイルをアップロードします。

既にアップロード済みの場合は5に進んでください。

4-1: 右上の[0100]アイコン(File and Add Data)アイコンをクリックします。

尚、Notebookは編集モードでないとこのアイコンはクリックできません。もし編集モードになっていない場合は、「えんびつ」アイコンがあると思いますので、そちらをクリックして編集モードにしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/6bf770ec-e862-c5b4-5a93-2b250a850878.png)


4-2: 表示された「ここにファイルをドラッグ・アンド・ドロップするか、アップロードしてください。」が書いてある四角いエリアに、アップロードしたいファイルをドラッグ&ドロップします。あるいは「ここにファイルをドラッグ・アンド・ドロップするか、アップロードしてください。」をクリックするとファイルダイアログが表示されますので、そこから選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/4e31eeff-d1b1-ffe1-73a4-a244cad44cf1.png)


しばらくするとファイルがロードされ、ロードしたファイル名が下に表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/9f570038-508d-4e4d-8a4c-0e1fd487d510.png)

#5: プロジェクト・トークンの挿入
5-1: 上部メニューの縦の・・・をクリックし、「プロジェクト・トークンの挿入」をクリックします。

[#2. 前準備 `アクセス・トークン`の作成](#2)でアクセス・トークンを作成してないと、このメニューは表示されないので、もし表示されてない場合は、[#2. 前準備 `アクセス・トークン`の作成](#2)を実施しているか確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/571828a4-ab71-8ac1-bffd-d03609701c1f.png)



**一番上のセル**にhidden_cellとして`project-lib`を使うためのライブラリを読み込み、設定したProject tokenを使用して必要なコードが書かれたセルが挿入されます。

notebookの下の方で作業していたとしても、必ず一番上のセルに挿入されるので、見当たらない場合は一番上のセルまでスクロールしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/45a09a6e-92d2-da6e-12e3-5904cb13417f.png)

5-2: セルをクリックして以下のいずれかの方法で実行をします。

 - [Shift] + [Enter] を入力
 - 上のメニューから`▶︎Run` ボタンをクリック
   - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/9b29656d-29ad-a8d3-caa3-f243680222c1.png)


実行が完了すると以下の部分に数字が入ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/326d0d01-4002-8e5a-0f4f-3a305563abb9.png)

これでnotebookの準備は完了です。この作業はnotebook毎に１回必要です。

#6: ファイル読み書き方法
では早速notebook上でProjectのICOS経由ファイルを読み書きしてみましょう。#5で挿入されたセルは実行済みの前提です。

##6.1: ICOS <-> notebook VM間のファイルのコピー
よく本などに載っているサンプルコードでファイルを扱うものは、localのストレージ直で読み書きするものです。notebookの場合、notebookを編集状態にするたびにVMが立ち上がりますので、その領域にファイルをコピーしておけば、localのストレージにあるのと同じですので、サンプルコードはそのまま使えます。逆にサンプルコードで保存した場合は、VM領域にコピーされてますので、notebookを閉じる前に、ICOSにコピーしておけば、notebookを閉じてもファイルは保存され、ダウンロードも可能です。

### ICOSからVMへのコピー

```py
#Copy a file in project ICOS to VM
csv_file_name = 'train.csv'
csv_file = project.get_file(csv_file_name)
csv_file.seek(0)
with open(csv_file_name,'wb') as out:                   
    out.write(csv_file.read())   
```

コピーができたかどうかは以下のコマンドをセルで実行すれば確認できます。`!`を先頭につけるとVMのOSコマンド(Linuxコマンド)が実行できます。

```py
!ls -la
```
実行例:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/a0554f8f-b540-4e3b-bb22-e560e1c7c70c.png)



### VMからICOSへのコピー
上記でVM上にコピーしたファイルをICOSにコピーします。コピーしたファイル名は`copy_train.csv`としています。

```py
#Copy a file in VM to project ICOS
with open('train.csv','rb') as f:
    project.save_data('copy_train.csv', f, overwrite=True)
```

確認は一旦notebookを閉じて行います。「1.Save」して「２.Project名をクリックして」notebookを閉じてください。Projectの画面が開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/116b0a5c-7cf5-203d-0a98-f538000af72b.png)

Assetsタブの`Data assets`の下にコピーしたファイルがあります:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/ebdfd12d-526b-2118-bee7-714376490ceb.png)

以下はその他直接読み書きする方法です。
### pandasのDataFrameにICOSから読み込む
```py
csv_file_name = 'train.csv'
csv_file = project.get_file(csv_file_name)
csv_file.seek(0)

import pandas as pd
df_csv= pd.read_csv(csv_file)
df_csv
```
実行例:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/12995610-fa73-9d19-0f5c-e6856037ff82.png)

### pandasのDataFrameからICOSにCSV保存
上記で読み込んだDataFrame, df_csvをcopy_train.csvという名前でICOSに保存します。

```py
project.save_data("copy_train.csv", df_csv.to_csv(index=False), overwrite=True)
```

確認方法は[VMからICOSへのコピー](#vm%E3%81%8B%E3%82%89icos%E3%81%B8%E3%81%AE%E3%82%B3%E3%83%94%E3%83%BC)と同じです。

### VisualRecognition のAPIのパラメーターとして渡す
イメージファイルをICOSにアップロードしておいて、それをWatsonのVisial Recognitionの認識ファイルとして渡すサンプルです。`sushi.jpg`ファイルがprojectのICOSにアップロードされているとします。

下記の2つはVisualRecognition のｓｄｋを使う前準備です。

```py
!pip install --upgrade "ibm-watson>=4.0.1,< 5.0"
```
`XXXXXXXXXXXXXX`には使用するVisual RecognitionのAPIKEYを入れてください。

```py
#Visual Recognition
API_KEY='XXXXXXXXXXXXXX'　#replace XXXXXXXXXXXXXX to your APIKEY

from ibm_watson import VisualRecognitionV3
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

authenticator = IAMAuthenticator(API_KEY)
visual_recognition = VisualRecognitionV3(
    version='2018-03-19',
    authenticator=authenticator
)
```

以下がproject-libを使ったサンプルコードです：

```py
import json
image_file = project.get_file("sushi.jpg")
image_file.seek(0)
classes = visual_recognition.classify(
        images_file=image_file,
        images_filename='sushi.jpg',    
        threshold='0.6',
       accept_language='ja').get_result()

#結果確認
print(json.dumps(classes, indent=2, ensure_ascii=False))

```

### ICOSの画像表示
`sushi.jpg`という画像ファイルがprojectのICOSにアップロードされているとします。以下のコードでnotebook上に表示できます。

```py
#Image
image_file = project.get_file("sushi.jpg")
image_file.seek(0)
from IPython.display import Image
Image(data=image_file.read()) 
```

以上です。

#7: まとめ
いかがでしたか? 最初に設定が必要ですが、一度設定すれば以外に簡単にコードが書けたと思います。project.get_file()で戻ってくるのはio.BytesIOなのでいろいろ書けると思いますので、Watson Studioのドキュメント「[Using project-lib for Python](https://dataplatform.cloud.ibm.com/docs/content/wsj/analyze-data/project-lib-python.html)」の情報を参考に他にもいろいろお試しいただければと思います。