20220115のPythonに関する記事は26件です。

numpyチュートリアル on Jupyter Notebook

numpyチュートリアル(ビギナーズ向け)及びnumpyクイックスタートのWebサイトの内容を翻訳しJupyter Notebookで実際に動かしながら学習できるように編集しました。 元にしたWebサイトはこちら     オリジナルのサイトに加え、わかりにくいと思われる箇所の補足説明や、全てのコードが実行できるようにテストデータを作成するコードの追加等を実施しています。 numpy の学習ツールとして活用ください。 下記のGithubのサイトからファイルをダウンロードして、Jupyter notebook環境、またはGoogleコラボ上で実行してください。 NumPy the absolute basics for beginners.ipynb : numpyチュートリアル(ビキナーズ向け) Numpy quickStart.ipynb : numpyクイックスタート なお、numpyチュートリアル(ビギナーズ向け)の翻訳のWeb版を下記で公開しています。 実行まで必要としない場合はこちらを参照ください。   また、「Pythontyチュートリアル」も同様に動かしながら学習できるように下記で公開していますので合わせてご活用ください。 サンプルイメージ 上記コンテンツのサンプルイメージです。 ・・・ ・・・ 補足説明の例 テストデータ生成の例 参考 Googleコラボをまだ使ったことがない方は下記を参考にしてください。 Googleコラボのインストールは、以下の手順で簡単に行えます。 Gooleアカウトを作成(まだ持っていない場合) Googleドライブ上で左上のメニューから「アプリで開く」->「アプリを追加」で、Googleコラボ  を選んでインストール Githubからアップロードしたファイルを実行するとGoogleコラボで起動します 誤りや不足、加筆修正すべきところがありましたらぜひご指摘ください。継続してブラッシュアップしていきます。 © 2022 NPO法人AI開発推進協会
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SeleniumでDeepL翻訳

はじめに DeepL( https://www.deepl.com/ja/translator) での翻訳を、Seleniumを用いて行います。 例として、ニューサイトから取得した記事( https://news.google.com/rss?hl=en-US&gl=US&ceid=US:en )のタイトルの英語の翻訳を行っていきます。前回の記事の続きのような内容ですので、スクレイピング部分は、下の記事を参照してください。 前回の記事:ニュース記事をスクレイピング 目次 翻訳の全体像 翻訳を行うコード 参考文献 翻訳の全体像 Seleniumを用いてDeepL翻訳を行います。Seleniumのインストールは、下の記事などを参考にしてください。 参考: 10分で理解する Selenium - Qiita DeepLのページをSeleniumを用いて、操作します。DeepLのページに行き、一旦、好きな言葉を翻訳してみてください。私は、前回の記事でとってきた、記事のタイトルを入れてみます。 うまく翻訳ができています。ここで注目すべきは、この時のURLです。 https://www.deepl.com/ja/translator#en/ja/Biden%20says%20he's%20%22not%20sure%22%20about%20voting%20bills'%20future%20after%20Sinema%20reiterates%20opposition%20to%20rule%20change%20-%20CBS%20News 元々のURLは、https://www.deepl.com/ja/translator でした。 つまり、元のURL + #翻訳前の言語/翻訳語の言語/翻訳したい内容 になっていることがわかります。しかし、翻訳したい内容は、%20などの余分な文字が追加されています。 ですので、今回の操作の流れは、次のように表せます。 Google Chromeを立ち上げる 翻訳したい内容を含めたURLにアクセス 翻訳したデータを取得する 翻訳を行うコード 翻訳を行うには、ChromeDriverが必要です。ダウンロードはこちらで行えます。 (→ https://chromedriver.chromium.org/downloads ) 下のコードは、英語の"Biden says he's "not sure" about voting bills' future after Sinema reiterates opposition to rule change - CBS News"を日本語に翻訳するコードです。 translate.py import time import urllib.parse import lxml from bs4 import BeautifulSoup from selenium import webdriver from selenium.webdriver.chrome.options import Options # text = 翻訳したい文章 text = "Biden says he's "not sure" about voting bills' future after Sinema reiterates opposition to rule change - CBS News" text = urllib.parse.quote(text) # URL作成 from_lang = 'en' to_lang = 'ja' url = 'https://www.deepl.com/translator#' + from_lang +'/' + to_lang + '/' + text # ヘッドレスモードでブラウザを起動 options = Options() options.add_argument('--headless') # ブラウザーを起動 DRIVER_PATH = "./chromedriver" # 自分のchromedriverまでのパス driver = webdriver.Chrome(DRIVER_PATH, options=options) driver.get(url) driver.implicitly_wait(30) # 見つからないときは、30秒まで待つ # DeepLの翻訳部分 sleep_time = 10 try_max_count = 30 for i in range(try_max_count): # 指定時間待つ time.sleep(sleep_time) html = driver.page_source soup = BeautifulSoup(html, features='lxml') target_elem = soup.find(class_="lmt__translations_as_text__text_btn") translated_text = target_elem.text # DeepLの翻訳が終わっている確認 if translated_text: break # ブラウザ停止 driver.quit() 参考文献 前回記事 ニュースサイト
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ニュース記事をスクレイピング (DeepLで翻訳)

はじめに ニューサイトから取得した記事( https://news.google.com/rss?hl=en-US&gl=US&ceid=US:en )のタイトルが、英語なので、翻訳を行っていきます。翻訳には、DeepL( https://www.deepl.com/ja/translator) を用います。 前回の記事:ニュース記事をスクレイピング 目次 翻訳の全体像 翻訳を行うコード 参考文献 翻訳の全体像 今回は、Seleniumを用いた手法を紹介します。Seleniumのインストールは、下の記事などを参考にしてください。 参考: 10分で理解する Selenium - Qiita DeepLのページをSeleniumを用いて、操作します。DeepLのページに行き、一旦、好きな言葉を翻訳してみてください。私は、前回の記事のタイトルを入れてみます。 うまく翻訳ができています。ここで注目すべきは、この時のURLです。 https://www.deepl.com/ja/translator#en/ja/Biden%20says%20he's%20%22not%20sure%22%20about%20voting%20bills'%20future%20after%20Sinema%20reiterates%20opposition%20to%20rule%20change%20-%20CBS%20News 元々のURLは、https://www.deepl.com/ja/translator でした。 つまり、元のURL + #翻訳前の言語/翻訳語の言語/翻訳したい内容 になっていることがわかります。しかし、翻訳したい内容は、%20などの余分な文字が追加されています。 ですので、今回の操作の流れは、次のように表せます。 Google Chromeを立ち上げる 翻訳したい内容を含めたURLにアクセス 翻訳したデータを取得する 翻訳を行うコード 翻訳を行うには、ChromeDriverが必要です。ダウンロードはこちらで行えます。 (→ https://chromedriver.chromium.org/downloads ) 下のコードは、英語の"Biden says he's "not sure" about voting bills' future after Sinema reiterates opposition to rule change - CBS News"を日本語に翻訳するコードです。 translate.py import time import urllib.parse import lxml from bs4 import BeautifulSoup from selenium import webdriver from selenium.webdriver.chrome.options import Options # text = 翻訳したい文章 text = "Biden says he's "not sure" about voting bills' future after Sinema reiterates opposition to rule change - CBS News" text = urllib.parse.quote(text) # URL作成 from_lang = 'en' to_lang = 'ja' url = 'https://www.deepl.com/translator#' + from_lang +'/' + to_lang + '/' + text # ヘッドレスモードでブラウザを起動 options = Options() options.add_argument('--headless') # ブラウザーを起動 DRIVER_PATH = "./chromedriver" # 自分のchromedriverまでのパス driver = webdriver.Chrome(DRIVER_PATH, options=options) driver.get(url) driver.implicitly_wait(30) # 見つからないときは、30秒まで待つ # DeepLの翻訳部分 sleep_time = 10 try_max_count = 30 for i in range(try_max_count): # 指定時間待つ time.sleep(sleep_time) html = driver.page_source soup = BeautifulSoup(html, features='lxml') target_elem = soup.find(class_="lmt__translations_as_text__text_btn") translated_text = target_elem.text # DeepLの翻訳が終わっている確認 if translated_text: break # ブラウザ停止 driver.quit() 参考文献 前回記事 ニュースサイト
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MySQL5.7でPolygonの内外判定

はじめに いままでポリゴンの内外判定はPythonでしかやったことがありませんでしたが、MySQLでもポリゴンの内外判定ができるらしく、使い勝手もよさそうなので試してみました。 geometry型 MySQLではgeometry型という位置情報系のデータ型を用いることができます。 これによってポリゴンなどのデータもデータベース側に持つことができます Polygonの内外判定 ST_Containsという関数を用いればポリゴンの内外判定ができます。 たとえばgeometriesテーブルという、geometry型のpolygonカラムを持つテーブルがあったとして、以下のようなクエリを叩けば、緯度経度35.67405, 139.77250の位置を含むレコードが返ってきます。 SELECT * FROM geometries WHERE ST_Contains(polygon, GeomFromText("POINT(139.77250 35.67405)")) = 1 ; 実際に試してみる 実際に動作して確かめてみましょう。今回ポリゴンのサンプルデータとして使うのは以下の記事でも用いた、政府統計のe-Statからダウンロードできる東京都の境界データです。 急いでる人向け ちなみに今回用いたコードは全てGithubにあげているので、とりあえず動かすところまでやりたい方はこのリポジトリをcloneしてREADMEの通りに実行してみてください。 MySQLサーバ立ち上げ MySQLでデータベースを作成したいのですが、今回はdockerを使っていきます。 以下のようなdocker-composeファイルを用意します。 docker-compose.yml version: "2" services: mysql: container_name: mysql_host image: mysql:5.7.12 ports: - 3306:3306 environment: TZ: Asia/Tokyo MYSQL_ROOT_PASSWORD: rootpw MYSQL_DATABASE: sample_db MYSQL_USER: user MYSQL_PASSWORD: E9c9y6IwaDzNtLAfJn3qd3Sa20pOCz BIND-ADDRESS: 0.0.0.0 tty: true command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci 詳しくは解説しないですが、以下のコマンドでmysqlサーバが立ち上がります docker-compose up -d docker-compose psして以下のように表示されればちゃんと立ち上がってます。 $ docker-compose ps Name Command State Ports ---------------------------------------------------------------------------- mysql_host docker-entrypoint.sh mysql ... Up 0.0.0.0:3306->3306/tcp mysqlにアクセス ローカルからデータベースにログインしてみましょう。 # ローカルにMySQLがインストール済みなことが前提 mysql -h 127.0.0.1 -uroot -prootpw でアクセスできるはずです。 データベース、geometriesテーブルの作成 ログイン後、以下のコマンドでsample_dbデータベースにgeometriesテーブルを作ります。 CREATE DATABASE IF NOT EXISTS sample_db; USE sample_db; DROP TABLE IF EXISTS `geometries`; CREATE TABLE IF NOT EXISTS `geometries` ( `id` int(11) NOT NULL AUTO_INCREMENT, `addressCode` varchar(255) NOT NULL, `address` varchar(255) NOT NULL, `polygon` geometry NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 東京都の境界データをgeometriesテーブルに挿入 ここからは挿入するデータの量も多いのと、データ整形も必要なのでPythonで作業していきます。 まずPython経由でMySQLにアクセスする必要があるので、以下のパッケージをpip経由などでインストールしておきます。 pip install sqlalchemy pymysql PythonからInsertしたいので、以下の関数を定義しておきます。 from sqlalchemy import create_engine def execute(sql, user, password, host, port, db): con = f'mysql+pymysql://{user}:{password}@{host}:{port}/{db}' engine = create_engine(con) connect = engine.connect() connect.execute(sql) connect.close() 次に、政府統計のe-Statから東京都全域の境界データをダウンロードしてから解凍し、どこかのフォルダに置いておきます。(そのディレクトの相対パスを./data/A002005212015DDSWC13/ということにしておきます。) shapefileをデータフレームとして扱いたいので、geopandasをインストールしておきます。 pip install geopandas 以下のようにshapefileを読み込み、軽くデータ整形しておきます。 import geopandas gdf = geopandas.read_file('./data/A002005212015DDSWC13/h27ka13.shp') gdf['addressCode'] = gdf.apply( lambda x: str(x['PREF']) + str(x['CITY']) + str(x['S_AREA']), axis=1) gdf['address'] = gdf.apply( lambda x: x['PREF_NAME'] + x['CITY_NAME'] + (x['S_NAME'] if x['S_NAME'] is not None else ''), axis=1) gdf[['addressCode', 'address', 'geometry']] geometry型のカラムにデータを挿入するためには、 POLYGON ((140.34225 29.79356, 140.34149 29.793...)) となっているgeometry文字列を GeomFromText('POLYGON ((140.34225 29.79356, 140.34149 29.793...))') のように変換してあげる必要があります。 そのため、Insert文は以下のように生成でき(geo_text)、これを先ほど作ったexecute関数で実行します。(先に断っておくと、おそらくこの処理は失敗します。) geo_text_list = [ f"('{r['addressCode']}', '{r['address']}', GeomFromText('{r['geometry']}'))" for _, r in gdf.iterrows()] geo_text = ','.join(_geo_text_list) execute( f''' INSERT INTO geometries (addressCode, address, polygon) VALUES {geo_text} ; ''', user='root', password='rootpw', host='127.0.0.1', port=3306, db='sample_db' ) ただこれだとInsertするデータが多すぎておそらく失敗します。そのため、いくつかの処理にわけてInsertしたほうがうまくいく可能性が上がります。 import numpy as np geo_text_list = [ f"('{r['addressCode']}', '{r['address']}', GeomFromText('{r['geometry']}'))" for _, r in gdf.iterrows()] # geo_text_listをひとつの要素数が100個くらいになるように分割 split_num = 100 geo_text_list_split = [list(_) for _ in np.array_split( geo_text_list, len(geo_text_list)//split_num)] print('insert into geometries.') print(f'num of insert records: {len(geo_text_list)}') for _geo_text_list in geo_text_list_split: geo_text = ','.join(_geo_text_list) execute( f''' INSERT INTO geometries (addressCode, address, polygon) VALUES {geo_text} ; ''', user='root', password='rootpw', host='127.0.0.1', port=3306, db='sample_db' ) おそらくこれで挿入がうまくいっているはずです。念のため、上のコード出力させたnum of insert recordsの値と、SELECT COUNT(*) FROM geometries;の出力結果が同じであることを確認しておいてください。 ST_Containsで内外判定 ここまでできたら、あとは冒頭のクエリをなげて試すだけです。 $ mysql -h 127.0.0.1 -uroot -prootpw sample_db mysql> SELECT -> id, -> addressCode, -> address -> FROM -> geometries -> WHERE ST_Contains(polygon, GeomFromText("POINT(139.77250 35.67405)")) = 1 -> ; +-------+-------------+-----------------------------------+ | id | addressCode | address | +-------+-------------+-----------------------------------+ | 17256 | 13102003001 | 東京都中央区銀座1丁目 | +-------+-------------+-----------------------------------+ 1 row in set, 1 warning (0.10 sec) 上のように返ってくれば成功です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

im2colの実装で出てくる式を視覚化してみます

有名な「ゼロから作るDL」? 第7章に出てくる"im2col"。 im2colの定義式について問う問題が、某E資格対策講座の教材で出題されましたので、 図に書いて自分用にメモを取りました。 「視覚的に、なんとなく」 わかってもらえたら幸いです。 im2colのソースコードはどなたでも閲覧可能です。 im2colの概要については、「ゼロつく」 やその他にお譲りします..。 今回はこのソースコード中の col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride] という式 だけ に注目して、解説します!(せまい!) 一応、E資格講座の質問担当様にも、理解に間違いがないかチェックしていただきました。 1. まずは簡単のため、前提条件はこんな感じとします。 4 × 4の画像がRGBの3チャンネルあるとします。 ストライドやフィルターの大きさは以下の通り。 pythonでは、例えば "0:4:2"という表記は、「0列目から4列目まで、2つ飛ばしで」という意味です。 2. 3. 4. 5. col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride] の式の右辺の意味は、4.までで(あくまでなんとなく)ご理解いただけたかと思います。 では、この右辺=左辺 とはどういうことか? というと、、 (4つの図は、それぞれ右辺にあたるものが左側、           左辺にあたるものが右側 にあるのでご注意ください) 以上が、 col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride] の視覚的な理解になります。 おまけ なお、その次に続く、最後の式 col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1) は、詳細までは力尽きて視覚化できませんでしたが、 以下の図のような変換をしている式とのことです。 ( (x,y)=(1,1) の時の例だけ載せています ) なんでこの式でこういう変換になるのか、途中を図示できる方はぜひぜひお願いします.. ぼくにはわからない.. おしまいです
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

im2colの実装で出てくる式をわかりやすく視覚化してみます

有名な「ゼロから作るDL」? 第7章に出てくる"im2col"。 im2colの定義式について問う問題が、某E資格対策講座の教材で出題されましたので、 図に書いて自分用にメモを取りました。 「視覚的に、なんとなく」 わかってもらえたら幸いです。 im2colのソースコードはどなたでも閲覧可能です。 リンク先githubの39〜68行目が該当します。 im2colの概要については、「ゼロつく」 やその他にお譲りします..。 今回はこのソースコード中の col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride] という式 だけ に注目して、解説します!(せまい!) 一応、E資格講座の質問担当様にも、理解に間違いがないかチェックしていただきました。 この式、一見簡単そうに見えますが、よくよく見ると「?」 となるのはぼくだけでしょうか? 1. まずは簡単のため、前提条件はこんな感じとします。 4 × 4の画像がRGBの3チャンネルあるとします。 ストライドやフィルターの大きさは以下の通り。 pythonでは、例えば "0:4:2"という表記は、「0列目から4列目まで、2つ飛ばしで」という意味です。 2. 3. 4. 5. col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride] の式の右辺の意味は、4.までで(あくまでなんとなく)ご理解いただけたかと思います。 では、この右辺=左辺 とはどういうことか? というと、、 (4つの図は、それぞれ右辺にあたるものが左側、           左辺にあたるものが右側 にあるのでご注意ください) 以上が、 col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride] の視覚的な理解になります。 おまけ なお、その次に続く、最後の式 col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1) は、詳細までは力尽きて視覚化できませんでしたが、 以下の図のような変換をしている式とのことです。 ( (x,y)=(1,1) の時の例だけ載せています ) なんでこの式でこういう変換になるのか、途中を図示できる方はぜひぜひお願いします.. ぼくにはわからない.. おしまいです
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

python で deepL API を使ってみる

DeepL API Free DeepL は API を提供している。 無償版の DeepL API Free と 有償版の DeepL API Pro があり, 無償版の API をプライベートで使う機会があったので本記事にまとめる。 無償版と有償版では以下のような違いがある。 なお無償版, 有償版に関わらずアカウント登録とクレジットカード情報の登録が必要となる。 登録するクレジットカードは3Dセキュア認証に対応していなければならず, 加えて JCB は利用不可。 無償版から有償版へは手動で切り替えを行わない限り切り替わらないのでそこは安心。 また deepL は翻訳対象の文章を一定期間保存しているとのことなので, 気密性の高い文章を取り扱う際には要注意。 python で deepL API Free を呼び出す 実際に簡単例を実行してみる。 本例では文字列を渡してるが, ドキュメントファイルを渡すことも可能。 API の仕様については 公式ドキュメント を参照せよ。 translate.py import requests API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx' # 自身の API キーを指定 text = "Riemann Zeta function is a very important function in number theory." source_lang = 'EN' target_lang = 'JA' # パラメータの指定 params = { 'auth_key' : API_KEY, 'text' : text, 'source_lang' : source_lang, # 翻訳対象の言語 "target_lang": target_lang # 翻訳後の言語 } # リクエストを投げる request = requests.post("https://api-free.deepl.com/v2/translate", data=params) # URIは有償版, 無償版で異なるため要注意 result = request.json() print(result) 出力結果 { "translations": [ { "detected_source_language": "EN", "text": "リーマン・ゼータ関数は、整数論において非常に重要な関数である。" } ] } 翻訳する文章は文字列のリストとして渡してもよい。 translate.py import requests API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx' # 自身の API キーを指定 text = ["素数はとても魅力的な数です。", "素数の分布には今も多くの謎が残されています。"] source_lang = 'JA' target_lang = 'EN' # パラメータの指定 params = { 'auth_key' : API_KEY, 'text' : text, 'source_lang' : source_lang, # 翻訳対象の言語 "target_lang": target_lang # 翻訳後の言語 } # リクエストを投げる request = requests.post("https://api-free.deepl.com/v2/translate", data=params) # URIは有償版, 無償版で異なるため要注意 result = request.json() print(result) 出力結果 { "translations": [ { "detected_source_language": "JA", "text": "Prime numbers are very attractive numbers." }, { "detected_source_language": "JA", "text": "There are still many mysteries surrounding the distribution of prime numbers." } ] } クライアントライブラリ Python で deepL の API を利用するためのクライアントライブラリが公式から提供されている。 インストールは pip で可能。 pip install --upgrade deepl 使ってみる。 translate_client.py import deepl API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' # 自身の API キーを指定 text = 'Riemann Zeta function is a very important function in number theory.' source_lang = 'EN' target_lang = 'JA' # イニシャライズ translator = deepl.Translator(API_KEY) # 翻訳を実行 result = translator.translate_text(text, source_lang=source_lang, target_lang=target_lang) # print すると翻訳後の文章が出力される print(result) 実行結果 リーマン・ゼータ関数は、整数論において非常に重要な関数である。 こちらも text には文字列だけではなく, 文字列のリストを指定することが可能。 translate_client.py import deepl API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' # 自身の API キーを指定 text = ['コミュニケーションをとることは重要である。', '特にテレワークが主流となった昨今においては、コミュニケーション不足による弊害が多く報告されている。'] source_lang = 'JA' target_lang = 'EN-GB' # イニシャライズ translator = deepl.Translator(API_KEY) # 翻訳を実行 results = translator.translate_text(text, source_lang=source_lang, target_lang=target_lang) # results の中身はオブジェクトのリスト print(results) print('-'*30) for result in results : # print すると翻訳後の文章が出力される print(result) # 翻訳後の文章にアクセスする場合は .text で可能 # print(result.text) 出力結果 [<deepl.translator.TextResult object at 0x000001A15A4A84C0>, <deepl.translator.TextResult object at 0x000001A15C95C9A0>] ------------------------------ It is important to communicate. In recent years, especially as teleworking has become the norm, there have been many reports of the negative effects of poor communication.
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

サイトのキャプチャや自動OGP画像生成、動的サイトのHTML取得のSaas「WebNium」を公開

出来ること WebページキャプチャAPI 動的HTML取得API OGP画像自動生成 Saasのページは下記 作ろうと思ったきっかけ 画像キャプチャや動的サイト(javascriptが動いてHTMLが生成されるサイトSPA等)のHTMLを取得したいということがよくあり、 しかし、そのためにseleniumを実行したりするのがめんどくさいなーってことで、簡単に扱えるWebApiをと思った SPAで動的OGPを実装したかった(後に、metaタグを切り替えられないからOGP生成が動的であっても、ページごとにOGPを設定することは不可能だと分かる) 技術スタック フロントエンド typescript Vue.js Firebase Hosting バックエンド python Heroku データベース Firebase RealtimeDatabase 認証 Firebase Authentication OGP画像自動生成 前述の通り本当はSPAで、各ページの画像を切り替えたかったが、出来なかった とはいえ、OGPの画像を用意するのがダルいという場合はこれを使うとよいのかも ただ、認証とキャッシュが未実装なのがβであるというところ・・・。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

備忘録 2022年1月15日 EXCELVBA 命名規則 Markdown記法 matplotlibヒストグラム メタ構文変数についてなど

Python matplotlibヒストグラムの縦軸と横軸をいい感じにする Markdown記法 チートシート matplotlibヒストグラムの使い方ガイド rangeでデータの最大値、最小値を設定する これにより見やすい?ヒストグラムが作成できる matplotlib 軸回りの見た目を良くしたい 命名規則 メタ構文変数について サンプルプログラムに用いられる意味のない名称 hoge huga piyoには順番があるらしい(初知り) unconverted data remains: EXCEL 時間帯を表示する EXCEL VBA 命名規則 VBE フォントサイズの変更
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

書籍「最短コースでわかる PyTorch &深層学習プログラミング」3値分類モデルの決定境界の表示

はじめに 書籍「最短コースでわかる PyTorch &深層学習プログラミング」の著者です。 この本の姉妹版にあたる「最短コースでわかるディープラーニングの数学」の補足として、3値分類モデルの決定境界を求めるコードをアップしたところ、結構評判がいいようなので、調子にのってこちらの本でも同じことをやってみます。 書籍のリンクはこちら 2つの書籍は、まったく同じデータを例題で扱っており、こちらの本で3値分類モデルは7章に該当します。 Notebook全体のリンクは、こちらです。 考え方 決定境界とは、2つの確率値が等しくなる点の集まりです。つまり、 softmax関数の入力の時点で考えると、「2つの1次関数の計算結果が等しい場所」ということになります。 これを、重み行列とバイアスの言葉でいいかえると、重み行列とバイアスを当時に一列ずらして元の行列との差をとり、その結果で計算される1次関数の結果がゼロになる場所です。 ※ この考え方が成り立つのは正確にいうと例題で扱っている3値分類の場合に限定されます。4値以上の分類の場合は、決定境界の組み合わせがもっと複雑なので、計算もそれに対応して複雑になります。 これから紹介するコードはこの考えに基づいて実装されています。 実装コード紹介 これから紹介する実装コードは、書籍でいうとp.263で学習が終わり、weightとbiasの値の表示までできた後に追加したものです。 x, yの描画領域の計算 決定境界の直線を元の散布図と同時に表示しようとすると。決定境界の直線に引っ張られて、散布図の点と関係ない領域まで表示されてしまいます。そのことを防ぐために、x, yの描画領域をあらかじめ計算し、 axis関数で明示的に描画領域を指定するようにします。 ※ この考え方は一般論としては間違っていないのですが、今回の場合は、一番最後の図を見ると、こういう問題は起きなかったみたいです。つまり、結果論としては、y_min, y_maxの計算と、描画のときのaxis関数呼び出しは不要でした。 # x, yの描画領域計算 x_min = x_train[:,0].min() x_max = x_train[:,0].max() y_min = x_train[:,1].min() y_max = x_train[:,1].max() x_bound = torch.tensor([x_min, x_max]) # 結果確認 print(x_bound) 決定境界のyの値計算用関数 # 決定境界用の1次関数定義 # 決定境界用の1次関数定義 def d_bound(x, i, W, B): W1 = W[[2,0,1],:] W2 = W - W1 w = W2[i,:] B1 = B[[2,0,1]] B2 = B - B1 b = B2[i] v = -1/w[1]*(w[0]*x + b) return v 行列W2は上の説明に基づいて実装しています。 その後の計算は、 $ w_0 + w_1 x + w_2 y = 0$ をyについて解いた結果です。 決定境界のyの値を計算 今、定義した関数を使って、決定境界のyの値を計算していきます。決定境界は全部で3つあります。 # 決定境界のyの値を計算 W = net.l1.weight.data B = net.l1.bias.data y0_bound = d_bound(x_bound, 0, W, B) y1_bound = d_bound(x_bound, 1, W, B) y2_bound = d_bound(x_bound, 2, W, B) # 結果確認 print(y0_bound) print(y1_bound) print(y2_bound) tensor([3.0898, 4.9179], dtype=torch.float64) tensor([2.2871, 3.7670], dtype=torch.float64) tensor([3.7981, 5.9337], dtype=torch.float64) グラフ描画 これで準備は全部整いました。あとは、今計算で出したyの値を使ってplot関数で直線を書けばいいだけとなります。 # 散布図と決定境界の標示 # xとyの範囲を明示的に指定 plt.axis([x_min, x_max, y_min, y_max]) # 散布図 plt.scatter(x_t0[:,0], x_t0[:,1], marker='x', c='k', s=50, label='0 (setosa)') plt.scatter(x_t1[:,0], x_t1[:,1], marker='o', c='b', s=50, label='1 (versicolour)') plt.scatter(x_t2[:,0], x_t2[:,1], marker='+', c='k', s=50, label='2 (virginica)') # 決定境界 plt.plot(x_bound, y0_bound, label='2_0') plt.plot(x_bound, y1_bound, linestyle=':',label='0_1') plt.plot(x_bound, y2_bound,linestyle='-.',label='1_2') # 軸ラベルと凡例 plt.xlabel('sepal_length') plt.ylabel('petal_length') plt.legend() plt.show() 下のようなグラフが表示されれば成功です!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

requirements.txtを作るだけのアプリ

よくrequirements.txtを書くのを忘れる自分のために「requirements.txt Generator」を作った。 デモ 機能 Windows, Mac, Linux対応 言語選択 フォルダ検索 フォルダの複数選択 フォルダ詳細表示 パッケージ選択 バージョン選択 説明 主にFlaskで作り、PyFladeskなるものを使うと簡単にFlaskのアプリをデスクトップアプリにできるので、それをpyinstallerで.exeなり.appにした。フォルダ構造を表示するJavaScriptでは、jstreeを使用。 対応している言語は Python Python(ipynb) Julia Julia((ipynb) Go で、PythonとJuliaのみバージョンを記載するかどうかを選ぶことができる。 Pythonでパッケージをインストールするには $ pip install -r requirements.txt だが、Juliaではそういった機能なく? install.jl using Pkg; Pkg.add(open(f->readlines(f), "./requirements.txt")) このinstall.jlというファイルを作った上で $ julia install.jl とするのが良いと思う。もちろんREPLでも。 $ julia julia> using Pkg julia> Pkg.add(open(f->readlines(f), "./requirements.txt")) Goに対応させているのは、単純にパッケージをインストールすることがあるからというだけで、requirements.txtにまとめる必要はないのと思うが、一応追加しておいた。 settings.pyのデフォルトパスになっているDesktopを好きなフォルダ名に変更すれば、その直下のデータのjsonファイルが作成される。デスクトップに大量のデータがある人は、ちゃんと動作しない可能性があるが、作成されるjsonファイルの行数が10万行でも動いていたので、おそらく大丈夫だと思う。 今後 Githubには、それぞれのOSに対応したダウンロードリンクが張ってあるが、Windowsに関してはWindowsDefenderでブロックされ、Macでは破損しているとか何とかで、ダウンロードしたものは使えなかったのでどうにかしたい。 今後はコマンドで実行できるようにしたり、Webでも利用できるようにしたい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Pythonのリストのメソッドに慣れる

はじめに Pythonのリストメソッドの使い方を覚え書きです。 難しい事が書きません。 目次 append(x) insert(i, x) pop(i) remove(x) clear() リスト作成(サンプル) サンプルのリストを作成し、次から説明するメソッドを実行した時にどういう結果になるか、確かめながら進めます。 まず、11,12,13,14の4個の数値が入ったリストを作成します。 list >>> list = [11,12,13,14] >>> list [11, 12, 13, 14] リストのメソッド list.append(x) - リストの追加(最後に) リストの最後にxを追加します。 append >>> list.append(25) >>> list [11, 12, 13, 14, 25] はい、最後に'25'が追加されましたね。 list.insert(i, x) - 指定の場所へ挿入 i番目の前に、Xを挿入します。 insert >>> list.insert(2, 22) >>> list [11, 12, 22, 13, 14, 25] 2番目の前、つまり、 11が0番目、12が1番目、13が2番目なので、13の前に22を追加されましたね。 list.pop(i) - 指定の場所を削除 i番目を削除を追加します。戻り値は削除する値。 pop >>> list.pop(4) 14 >>> list [11, 12, 22, 13, 25] 4番目の14が結果として出力されて、14が削除されていますね。 list.remove(x) - 指定の値を削除 指定値を削除します。 popメソッドと違い、場所ではなく、値の指定です。 remove >>> list.pop(12) >>> list [11, 22, 13, 25] 指定した12が削除されていますね。 list.clear() - すべての要素をクリアする すべての要素がクリアされます。 remove >>> list.clear() >>> list [] 空になりましたね。すっきり!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【日本株】Pythonで日本の株価+主要指数を取得してDBへ格納する

はじめに 以前以下のような記事を書いてましたが、題材としていた株式投資メモが2021年の3月以降のサイト更新が止まってしまった模様。 そこで今回は代替え手段として自分で直接スクレイピングしないライブラリを使用した2パターン紹介します。 なお過去にPythonでWebスクレイピング①(スクレイピング事前知識)なんて記事書いた手前一応触れますが、どちらのライブラリもグレーな可能性がありますのでもし使用する場合自己責任で。 動作環境 OS : Windows10 pro Python : 3.8.3// Miniconda 4.9.1 yfinance : 0.1.63 investpy : 1.0.7 sqlite3:2.6.0 jupyter notebook 以下ライブラリ紹介部分は折りたたみ表現を使用してますので、気になる箇所だけクリック/タップで開いてください。 yfinance 米国yahooファイナンスからデータ取得するライブラリ。基本的にみんなこれ使ってる気がします。 yfinanceのサンプルコード 作者解説ページ:https://aroussi.com/post/python-yahoo-finance Github:https://github.com/ranaroussi/yfinance 米yahooのrobots.txt:https://finance.yahoo.com/robots.txt 導入:pip install yfinance TOYOTA_yfinance(2000~2021) import pandas as pd import yfinance as yf from pandas_datareader import data as pdr yf.pdr_override() #pandas_datareaderにオーバーライドさせる code = '7203.T' start = pd.to_datetime('2000-01-01') end = pd.to_datetime('2021-12-31') historical_data = pdr.get_data_yahoo(tickers=code, start=start, end=end, retry_count=1) print(historical_data.shape) #約20年分なので6千弱日のデータが取れてればOK display(historical_data.head(2)) #最初2日 display(historical_data.tail(2)) #最後2日 実行結果 [*********************100%***********************] 1 of 1 completed (5487, 6) Data Open High Low Close Adj Close Volume 2000-01-03 990.0 990.0 990.0 990.0 581.667480 0 2000-01-04 998.0 1000.0 972.0 988.0 580.492554 11145000 Data Open High Low Close Volume Change Pct 2021-12-29 2122.0 2129.0 2106.5 2110.5 2110.5 14440600 2021-12-30 2104.0 2116.0 2091.0 2105.5 2110.5 14009600 ん?出来高0?? → 後述。 investpy investing.comからデータ取得するライブラリ。 このライブラリは過去に検証した際にデータの不整合が多く「使えない」と判断してましたが・・・ investpyのサンプルコード APIリファレンス:https://investpy.readthedocs.io/api.html Github:https://github.com/alvarobartt/investpy investing.comのrobots.txt:https://jp.investing.com/robots.txt 導入:pip install investpy TOYOTA_investpy(2000~2021) import investpy code = "7203" #TOYOTA start = "01/01/2000" #2000年初 end = "31/12/2021" #2021年末 #★ここが最重要。「investpy.get_stock_historical_data」だと過去の私の判断と同じように・・★ search_result = investpy.search_quotes(text=code, countries=["japan"], products=["stocks"], n_results=1) historical_data = search_result.retrieve_historical_data(from_date=start, to_date=end) print(historical_data.shape) #約20年分なので6千弱日のデータが取れてればOK display(historical_data.head(2)) #最初2日 display(historical_data.tail(2)) #最後2日 実行結果 (5393, 6) Data Open High Low Close Volume Change Pct 2000-01-04 998.0 1000.0 972.0 988.0 11145000 -0.20 2000-01-05 938.0 980.0 934.0 978.0 26940000 -1.01 Data Open High Low Close Volume Change Pct 2021-12-29 2122.0 2129.0 2106.5 2110.5 14440600 -1.05 2021-12-30 2104.0 2116.0 2091.0 2105.5 14009600 -0.24 ん?yfinanceの取得行より行数が少ないのでは? → 後述 yfinanceとinvestpyで数が合わないのは?? 整合性確認 日本のyahoo!ファイナンスで確認 https://finance.yahoo.co.jp/quote/7203.T/history 日本では2000/1/4からデータが取得されているのに対して・・ 米国のyahoo!ファイナンス https://finance.yahoo.com/quote/7203.T/history?p=7203.T 米国での取得開始日は米国市場の開始日に合わせて2000/1/3からになっていることがわかる ※だからyfinance(米国yahoo)の方がデータが多くなる ※ちなみに出来高0の2000/1/3には昨年の最終取引日1999/12/30のデータが入っている 株価取得+DB格納(investpyバージョン) さて、前座はここまででここからが前回記事のバージョンアップ版 ・前回記事は2000年だけだったが、今回は1990年~今日までなので数が段違い ・前回記事のtry文で例外処理した無駄な失敗証券コードで時間をつぶさない(存在する証券コードのみ使用) ・主要指数も取得 ※今回は入れてないが暗号通貨や商品も取得可能 ①証券コードリスト作成 東証上場銘柄一覧を以下HPのExcelから取得する(一部IPO等含まれない可能性あり) さらにここに存在しない指数等の情報は個別でlist化しておく ※Investing.comでコードやシンボルを調べておく必要あり 証券コードリスト取得 #東証のHPより東証上場銘柄一覧情報を取得し、Excelで保存 url = "https://www.jpx.co.jp/markets/statistics-equities/misc/tvdivq0000001vg2-att/data_j.xls" r = requests.get(url) with open('data_j.xls', 'wb') as output: output.write(r.content) #Excelをデータフレームで開く stocklist = pd.read_excel("./data_j.xls") #日本の指数(225,トピ,マザーズ,ジャスダック,東証REIT,日経VI) index_list_jp = ['JP225', 'TOPX', 'MTHR', 'NOTC', 'TREIT', 'JNIV'] #指定した日本の指数とデータフレームからコード部分をlist化して統合する index_list_jp.extend(stocklist['コード'].tolist()) #米国指数(ダウ,sp500,ナス,ラッセル,ドル円,vix,WTI) index_list_us = ['DJI', 'SPX', 'IXIC', 'RUT', 'USD/JPY', 'VIX', 'T'] ②株価取得+DB格納 取得したListを使用して株価(指数ポイント)を取得し、DB格納する。 頻度が多いとBlockされるので必ず待機時間を入れる(今回は1.5秒にしたが、GitHubのisuueでは5秒のwaitが推奨されていた) investpy+sqlite(1990~2021) def get_brand(code, country): """株価/ポイント取得関数""" try: start = pd.to_datetime('1990/01/01').strftime("%d/%m/%Y") #取得開始日 end = dt.date.today().strftime("%d/%m/%Y") #取得終了日 code = str(code) if country=='jp': #日本関係のデータ data = investpy.search_quotes(text=code, countries=["japan"], n_results=1) elif country=='us': #US関係のデータ(ダウ等) data = investpy.search_quotes(text=code, countries=["united states"], n_results=1) #ヒストリカルデータ取得 historical_data = data.retrieve_historical_data(from_date=start, to_date=end) df = historical_data.reset_index() df = df.assign(code=code) #証券コードをデータフレームに統合 print(code+'取得完了') #デバッグ用の正常取得完了通知 except: print(code+'は存在しません') #万が一取得できなかった場合の把握通知 return None return df def brands_generator(index_list_jp, index_list_us): """データフレーム操作関数""" #空のデータフレーム作成 cols = ['Open', 'High', 'Low', 'Close', 'Volume', 'Change Pct', 'code'] df = pd.DataFrame(index=[], columns=cols) #まずJP関連を取得 for code in index_list_jp: brand = get_brand(code, 'jp') #引数にJP #情報が取得できていれば、情報を結合していく if brand is not None: df = pd.concat([df, brand]).reset_index(drop=True) #1.5秒間プログラムを停止する(Block対策) time.sleep(1.5) #同様にUS関連を取得 for code in index_list_us: brand = get_brand(code, 'us') #引数にUS if brand is not None: df = pd.concat([df, brand]).reset_index(drop=True) time.sleep(1.5) return df #②で作成したJPとUSの証券コードを引数で関数へ渡してデータフレーム取得 df = brands_generator(index_list_jp, index_list_us) #データベースを作成 db = sqlite3.connect('japan_stock_price.db', isolation_level=None) #priceテーブルに収集したデータフレームを格納する df.to_sql('price', db, if_exists='append', index=None, method='multi', chunksize=5000) 実行結果 JP225取得完了 TOPX取得完了 ・ ・ VIX取得完了 T取得完了 ③TOYOTAを取り出してチャートを表示させてみる 確認も込みで適当に表示させてみる ※チャートは何のライブラリでもOK。今回はplotly(pip install plotly)使用 Plotlyを使ってTOYOTAのチャート確認 import plotly.graph_objects as go toyota_df = df[df['code']==str(7203)]#TOYOTAのみ抜粋 display(toyota_df.head(2)) #抜粋したDFを確認(2行) fig = go.Figure( data=[go.Candlestick(x=toyota_df["Date"], open=toyota_df["Open"], high=toyota_df["High"], low=toyota_df["Low"], close=toyota_df["Close"], name="TOYOTA")] ) fig.show() おわりに 前回記事が好評だったけど使えなくなってしまったので、代替え案として記事化してみました。 また、今回はinvestpyをメインで解説しましたが、ケースに応じて使い分ければいいと思います。 他にもファンダメンタルズデータ等の取得も可能なので自分だけの分析DBを作ってみてはいかがでしょうか? 【重要】本記事を参考に色々分析してわかった知見は、こっそりTwitterのDM経由で教えてください笑
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プログラミング未経験のOLが作る!スイーツ画像識別アプリ

はじめに アパレル会社勤務のOLがAIに興味を持ち、エンジニアを目指すべくプログラミングの勉強を始めました。 この記事はプログラミングスクールAidemyさんの最終課題である、画像識別アプリを作成する過程を記録したものです。 「いつかスイーツ大国フランスで本場の味を!」 という憧れからフランス菓子をアプリのテーマに決めました。 かの有名なラデュレのマカロン大好きです。 目次 実行環境 画像収集 画像の読み込み,データ分割 CNNモデルの作成,学習 HTML,CSSのコーディング FLASKのコード作成 アプリのデプロイ,動作確認,リンク先 考察,感想 参考文献 1. 実行環境 ・Python 3.7.12 ・Windows 10 ・Google Colaboratory ・Visual Studio Code 2. 画像収集 テーマの選定ができたので学習に必要な画像を収集していきます。 集める画像はマカロン、カヌレ、オランジェット、ダックワーズ、シュークリーム、エクレア、フロランタン、シャルロットの8種類です。 この8種類はフロント画面に使用するイラストに関連しています。 今回icrawlerを用いて画像を一括ダウンロードしました。 icrawlerはpythonでwebクローリングを行い画像を集めるためのフレームワークです。 短いコードを記述するだけで画像を集めることができました。 #モジュールをインポート from icrawler.builtin import BingImageCrawler import glob #検索リストの生成(日本語もOK) search_words = ["マカロン","カヌレ","オランジェット","ダックワーズ","シュークリーム","エクレア","フロランタン","シャルロット お菓子"] dir_names = ["マカロン","カヌレ","オランジェット","ダックワーズ","シュークリーム","エクレア","フロランタン","シャルロット"] for search_word,dir_name in zip(search_words,dir_names): # Bing用クローラーの生成 bing_crawler = BingImageCrawler( downloader_threads=4, # ダウンローダーのスレッド数 storage={'root_dir': "/content/drive/MyDrive/成果物2/"+dir_name}) # ダウンロード先のディレクトリ名 # クロール(キーワード検索による画像収集)の実行 bing_crawler.crawl( keyword=search_word, max_num=300) # ダウンロードする画像の最大枚数 ダウンロードした画像の一部です。 コード内で画像の最大枚数を300枚に指定しましたが、ダウンロードされたのは各200枚ずつくらいでした。 そこから各スイーツの特徴がしっかり写っている画像を厳選し100~130枚ほど収集しました。 画像を間引く作業は人力です。 3. 画像の読み込み,データ分割 学習の準備をしていきます。 Googleドライブ内にダウンロードされた画像をGoogle Colaboratoryで読み込みます。 正解ラベルを付けた後に、データを訓練データ8割と検証データ2割に分割します。 import os import cv2 import numpy as np import matplotlib.pyplot as plt from keras.utils.np_utils import to_categorical from keras.layers import Dense, Dropout, Flatten, Input from keras.applications.vgg16 import VGG16 from keras.models import Model, Sequential from tensorflow.keras import optimizers #パスに使用するスイーツの名前リスト sweets_lists = ["マカロン","カヌレ","オランジェット","ダックワーズ","シュークリーム","エクレア","フロランタン","シャルロット"] sweets_paths = [] #画像ファイルのパスを取得 for i in range(len(sweets_lists)): sweets_path = os.listdir('/content/drive/MyDrive/成果物2/'+sweets_lists[i]) sweets_paths.append(sweets_path) #画像ファイルの読み込み img_sweets = [] for i in range(len(sweets_lists)): for j in range(len(sweets_paths[i])): img = cv2.imread('/content/drive/MyDrive/成果物2/' + sweets_lists[i] + '/' + sweets_paths[i][j]) img = cv2.resize(img, (200,200)) img_sweets.append(img) # 画像データをnumpy配列に変換して正解ラベルを付ける X = np.array(img_sweets) y = np.array([0]*len(sweets_paths[0]) + [1]*len(sweets_paths[1]) + [2]*len(sweets_paths[2]) + [3]*len(sweets_paths[3]) + [4]*len(sweets_paths[4]) + [5]*len(sweets_paths[5]) + [6]*len(sweets_paths[6]) + [7]*len(sweets_paths[7])) # 画像データをシャッフル rand_index = np.random.permutation(np.arange(len(X))) X = X[rand_index] y = y[rand_index] # 訓練データと検証データに分割 X_train = X[:int(len(X)*0.8)] y_train = y[:int(len(y)*0.8)] X_test = X[int(len(X)*0.8):] y_test = y[int(len(y)*0.8):] # 正解ラベルをone-hotベクトルに変換 y_train = to_categorical(y_train) y_test = to_categorical(y_test) 4. CNNモデルの作成,学習 CNNモデルの作成と学習を実施していきます。 VGG16で学習を進めていたところ正解率が80%手前までしか上がらなかったため、Inception-v3にモデルを変更しました。 Inception-v3はImageNetと呼ばれる大規模な画像データセットに対して画像の分類精度を競うコンペティションILSVRCで2014年に優勝したモデルです。 VGG16同様1,000クラスの画像分類を行うよう学習されています。 次にハイパーパラメータの変更と検証です。 Global Average Pooling 層を利用することで全結合層によるパラメータ数の増加を防ぎ、Dropoutを使わずに過学習を抑制している。 入力サイズを(200, 200)として画質を上げると精度が高くなった。 epochsを10ずつ重ねて様子を見る。vall_lossは下がり、val_accuracy上がり順調に推移していった。 最終的な全体のコードは以下のようになりました。 from keras.applications.inception_v3 import InceptionV3 from keras.layers.pooling import GlobalAveragePooling2D # モデルにInception-v3を使用する input_tensor = Input(shape=(200, 200, 3)) inception_v3 = InceptionV3(include_top=False, weights="imagenet", input_tensor=input_tensor) top_model = Sequential() top_model.add(GlobalAveragePooling2D()) top_model.add(Dense(1024, activation='relu')) top_model.add(Dense(8, activation='softmax')) # モデルの連結 model = Model(inputs=inception_v3.input, outputs=top_model(inception_v3.output)) # コンパイル model.compile(loss='categorical_crossentropy', optimizer=optimizers.SGD(lr=1e-4, momentum=0.9), metrics=['accuracy']) # 学習の実行 model.fit(X_train, y_train, batch_size=8, epochs=10, validation_data=(X_test, y_test)) #学習モデルを保存してダウンロード from google.colab import files result_dir = 'results' if not os.path.exists(result_dir): os.mkdir(result_dir) # 重みを保存 model.save(os.path.join(result_dir, 'model.h5')) files.download( '/content/results/model.h5' ) 正解率は約91%です。 オランジェットには2通りの形があり(丸いものと細長いもの)、見た目の特徴が異なる画像をひとつにまとめているのでF値が低くなるのではと心配していましたがなんとか大丈夫そうです。 それよりもシュークリームが予想外の低さを示してしまい気になりますが、時間も限られているので今回はこのまま続行します。 5. HTML,CSSのコーディング 次にHTML,CSSのコーディングを実施していきます。 全体のデザインとしては教材内で作成したアプリのデザインをベースに作成していきます。 フリー画像素材をダウンロードできるイラストACでかわいいイラストを見つけたのでbackground-imageとして使用することにします。 このイラスト内にあるスイーツを識別できるようにしました。 ヘッダーメニューにHOMEに戻ることができるリセットボタンと、識別できるフランス菓子の種類を別ウインドウで開けるように設定しました。 HTMLとCSSのコードです。 index.html <!DOCTYPE html> <html lang='ja'> <head> <meta charset='UTF-8'> <meta name='viewport' content="device-width, initial-scale=1.0"> <meta http-equiv='X-UA-Compatible' content="ie=edge"> <title>フランス菓子識別アプリ(8種類対応)</title> <link rel='stylesheet' href="./static/stylesheet.css"> </head> </body> <header> <div> <a class='home' href="{{url_for('upload_file')}}"> リセット </a> <a class='variety' href="{{url_for('c_type')}}" onClick="window.open('./templates/c_type.html','windowname','scrollbars=yes,width=550,height=450'); return false;"> 識別できるフランス菓子 </a> </div> </header> <div class='main'> <img class="title" src="./static/pic/top_img.jpg"> <h2> AIがスイーツ大国フランスのお菓子をお答えします</h2> <p class='img_send'>画像を送信してください</p> <form method='POST' enctype="multipart/form-data"> <input class='file_choose' type="file" name="file"> <input class='btn' value="送信" type="submit"> </form> <h3 class='answer'>{{answer}}</h3> </div> <footer> <small>&copy; 2022 E.Arakawa</small> </footer> </body> </html> stylesheet.css body{ max-width: 1920px; width: 100%; padding: 0px 0px; margin: 0 auto; background-color: #e69db5; display: flex; flex-direction: column; min-height:100vh; } header{ height: 40px; width: 100%; background-color: #f162aa; } .home{ width: 140px; color: #fff; line-height: 44px; text-align: center; display: block; transition: all 0.5s; text-decoration: none; float: left; } .variety{ width: 200px; color: #fff; line-height: 44px; text-align: center; display: block; transition: all 0.5s; text-decoration: none; float: left; } .home:hover { background-color: rgba(255, 255, 255, 0.3); width: 180px; } .variety:hover { background-color: rgba(255, 255, 255, 0.3); width: 250px; } .title{ background-size: cover; opacity: 0.8; border-bottom: 2px groove; } img{ width: 100%; height: 500px; } h2{ color: #444444; margin: 40px 0px; text-align: center; } .img_send{ color: #444444; margin: 50px 0px 30px 0px; text-align: center; font-size: 20px; } .answer{ color: #734e30; margin: 70px 0px 30px 0px; text-align: center; font-size: 25px; } form{ text-align: center; } .flower_info{ text-align: center; font-size: 20px; } .error_message{ color :orangered; text-align: center; font-size: 25px; } footer{ background-color: #f162aa; border-top: 3px ridge; text-align: center; height: 10px; width: 100%; padding: 0px 3px 10px 3px; margin-top: auto; } small{ color: #fff; } こちらが識別可能なフランス菓子の種類を記載した別ウインドウのコードです。 c_type.html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>識別できるフランス菓子の種類</title> <link rel="stylesheet" href="../static/c_type.css"> </head> <body> <h2> 識別できるフランス菓子は以下の8種です。 </h2> <div> <ul> <li>マカロン</li> <li>カヌレ</li> <li>オランジェット</li> <li>ダックワーズ</li> <li>シュークリーム</li> <li>エクレア</li> <li>フロランタン</li> <li>シャルロット</li> </ul> </div> <a href="#" onclick="window.close()">[閉じる]</a> c_type.css body{ background-color: #e69db5; text-align: center; } h2{ text-align: center; } div{ text-align: center; margin-left: -40px; margin-right: auto; } li{ list-style: none; } 完成したフロント画面です。 6. FLASKのコード作成 HTML,CSSのコード同様、Aidemyさんの手書き文字識別アプリのコードをベースに作成していきます。 main.py import os from flask import Flask, request, redirect, render_template, flash from werkzeug.utils import secure_filename from tensorflow.keras.models import Sequential, load_model from tensorflow.keras.preprocessing import image import numpy as np classes = ["マカロン","カヌレ","オランジェット","ダックワーズ","シュークリーム","エクレア","フロランタン","シャルロット"] image_size = 200 UPLOAD_FOLDER = "uploads" ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif']) app = Flask(__name__) def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS model = load_model('./model.h5')#学習済みモデルをロード @app.route('/', methods=['GET', 'POST']) def upload_file(): if request.method == 'POST': if 'file' not in request.files: flash('ファイルがありません') return redirect(request.url) file = request.files['file'] if file.filename == '': flash('ファイルがありません') return redirect(request.url) if file and allowed_file(file.filename): filename = secure_filename(file.filename) file.save(os.path.join(UPLOAD_FOLDER, filename)) filepath = os.path.join(UPLOAD_FOLDER, filename) #受け取った画像を読み込み、np形式に変換 img = image.load_img(filepath,target_size=(image_size,image_size)) img = image.img_to_array(img) data = np.array([img]) #変換したデータをモデルに渡して予測する result = model.predict(data)[0] predicted = result.argmax() pred_answer = "これは " + classes[predicted] + " です" return render_template("index.html",answer=pred_answer) return render_template("index.html",answer="") # 識別できるフランス菓子の種類(別ウインドウ) @app.route('/templates/c_type.html') def c_type(): return render_template('c_type.html') if __name__ == "__main__": port = int(os.environ.get('PORT', 8080)) app.run(host ='0.0.0.0',port = port) 7. アプリのデプロイ,動作確認,リンク先 Herokuにアプリをデプロイしていきます。 無事にデプロイできた後に動作確認です。 まずはイラスト中央のシャルロットの画像を使用してみます。 結果 もうひとつ、F値の低さが気になったシュークリームを見てみます。 結果 ふたつとも正解です。 さらに2通りの形が存在するオランジェットを正しく識別できるか試してみます。 結果 どちらの画像もオランジェットと答えることができました。 AIが導き出した答えの確認ができたので、これでひとまず完成とします。 アプリのリンク先は下記になります。 ページが開くまで30秒ほどお待ちください。 フランス菓子識別アプリ(8種類対応) 8. 考察,感想 今回オリジナル画像のみでアプリ作成に挑みました。 画像のレベル(余計なものが写っている、中央に位置していない等)や枚数が画像識別の精度に大きく影響するのだと学びました。 自身の目で確認して特徴的な画像を厳選したつもりでしたが、AIにとっては情報が少なかったのだろうと思います。 画像を水増しするコードを加えても良かったかもしれないです。 教材内で使用したVGG16ではなくInception-v3を使用したので、ハイパーパラメータの調整と同様に転移学習に使用するモデルによって精度の改良に繋がることを身をもって知ることができました。 今後HTML、CSS、FLASKについてもしっかり勉強していきたいです。 本当に様々なエラーがありましたが、自分で切り抜けられるよう頑張って力を付けて行きたいです。 9. 参考文献 アラフォーが"ネコ"のネコ種を判別するAIアプリを作成してみた 画像データをキーワード検索で効率的に収集する方法(Python「icrawler」のBing検索) ILSVRC を振り返り CNN を deep に理解する① Qiita Markdown 書き方 まとめ イラストAC
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

白黒画像をカラーにしてくれるAPI DeOldify

かんたんに使える自動着色 昔の白黒写真をカラーに 昔の白黒写真をカラーにした動画などをみたことがないだろうか? あれをかんたんにつかえたら良くないですか? DeOldify かんたんに自動着色が行えるAPIである。 使い方 これだけで実行できる。 colorizer = get_image_colorizer(artistic=False) image_path = colorizer.plot_transformed_image_from_url(url=source_url, render_factor=35, compare=True, watermarked=False) Videoもできる。 ? フリーランスエンジニアです。 お仕事のご相談こちらまで rockyshikoku@gmail.com Core MLやARKitを使ったアプリを作っています。 機械学習/AR関連の情報を発信しています。 Twitter Medium
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Grasshopper で Shift JIS 形式のテキストデータを読み込む

はじめに Grasshopper の ReadFileコンポーネント でCSVデータを読み込んだら文字化けしてしまった。Shift JIS のテキストデータはエンコード指定が必要と教えていただいたのでやってみた。(kanano さんありがとうございます!) ReadFileコンポーネントはutf-8で書かれているみたいですね!shift-jisで読むにはスクリプトでエンコード指定する必要がありそうです。— kanano (@_kkanano) January 14, 2022 Pythonで文字コードをゴニョゴニョ GhPython Script コンポーネントのインプットを FileName アウトプットを txt に変更 「Python 文字コード」で検索すると山ほど情報が出てくるんだけど、GhPythonではうまく動かないものが多くいが意外と苦労した。最終的に成功したのはこちら txt = [] with open(FileName) as f: for line in f: txt.append(unicode(line, 'shift-jis')) 変換成功! C#でもやってみた このサイトを参考にC# Script コンポーネントでも作ってみた Shift_Jisで保存されたファイルを読み込んでUTF-8に変換する using ディレクティブに追記 using System.Text; using System.IO; RunScriptの中に追記 Encoding srcEncoding = Encoding.GetEncoding("shift_jis"); Encoding dstEncoding = Encoding.UTF8; using (var reader = new StreamReader(FileName, srcEncoding)) { string line = null; var strList = new List<string>(); while ((line = reader.ReadLine()) != null) { String convertedLine = dstEncoding.GetString( System.Text.Encoding.Convert( srcEncoding, dstEncoding, srcEncoding.GetBytes(line))); strList.Add(convertedLine); } txt = strList; }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Django】SNS app作成手順02-サインアップページ作成1

----------snsapp-urls.py---------- from xml.etree.ElementInclude import include from django.contrib import admin from django.urls import path urlpatterns = [ path('admin/', admin.site.urls), ] ⏬ from xml.etree.ElementInclude import include from django.contrib import admin from django.urls import path from .views import signupfanc urlpatterns = [ path('signup/', sigunupfanc), ] —————snsapp-views.py————— def signupfanc(request): return render(request,'signup.html',{}) —————snsフォルダ内にtemplates作成---------- —————templates内にsignup.htmml作成---------- —————サーバー立ち上げ---------- python3 manage.py runserver
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Django】SNS app作成手順01-初期設定

snspjというプロジェクトを作成する際のコマンドを記していく ----------初期設定---------- django-admin startproject snspj . python3 manage.py startapp snsapp ----------Settings.pyの中身を編集---------- INSTALLED_APPS の中へ追記 ‘snsapp.apps.SnsappConfig' TEMPLATESの'DIRS’:の後に追記 [BASE_DIR / 'templates’], —————snsappフォルダにもurls.pyを追加---------- —————snspj-urls.pyの内容をsnsapp-urls.pyへコピー---------- —————urls.pyの中身を編集---------- urlpatterns の中へ追記 path('',include('snsapp.urls’))
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Project Euler】Problem 30: 各桁の5乗の和

本記事はProjectEulerの「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。 問題 30:各桁の5乗の和 原文 Problem 30: Digit fifth powers 問題の要約:各桁の5乗の和が元の数と同じになる数の合計を求めよ この問題では数の範囲が指定されていないので、どこまで調べれば良いかがポイントですね。桁数が$d$のとき各桁の5乗の和の最大値は$(9^5 \times d)$となるのでプログラムで調べてみると。 for d in range(1,8): print(f"digit={d}, {10**(d-1)}-{10**d-1} {1}-{9**5*d}") d=1, 1-9 1-59049 d=2, 10-99 1-118098 d=3, 100-999 1-177147 d=4, 1000-9999 1-236196 d=5, 10000-99999 1-295245 d=6, 100000-999999 1-354294 d=7, 1000000-9999999 1-413343 7桁になると2つの値の範囲が重なっていないので、6桁まで、より正確にいうと$9^5*6=354294$までチェックすればよいので、以下のプログラムになります。 def digPowSum(n,pw): return sum([int(d)**pw for d in str(n)]) print(f"Answer: {sum([n for n in range(2,(9**5)*6+1) if n==digPowSum(n,5)])}") (開発環境:Google Colab)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Python selfの型を使う方法

メソッドの返り値の型をselfにする方法 というのも例えばクラスのメソッドの返り値でselfを返す時にそのselfを表す型をアノテーションに付けたいということがあることがあります。 例えば以下のようなユーザーを表すUserクラスがあったとします。 from typing import Optional class User: "ユーザークラスです。" name: str id: int description: Optional[str] = None age: Optional[int] = None def __init__(self, name: str, id: int): self.name, self.id = name, id def update_profile(self): "ユーザーのプロフィールを取得してこのクラスを拡張します。" # ここでユーザーのプロフィールを取得する。(便宜上ここでは変数の代入で表します。) description = "I wanna be the guy!" age = 5 # 新しいUserクラスのインスタンスを作り取得したデータを代入する。 self.description = description self.age = age return self このクラスのメソッドupdate_profileではユーザー情報を取得して取得したデータを自分の属性description等に書き込みます。 そしてインスタンスであるselfを返しています。 別にselfを返さなくても使えますがこうすることでこんなことができます。 name, age = "tasuren", 16 print(f"{name}の説明:", User(name, age).update_profile().description) もしselfを返さないようにした場合はこうなります。 name, age = "tasuren", 16 user = User(name, age) user.update_profile() print(f"{name}の説明:", user.description) 新しい変数を作ることになります。 なんか気分悪いです。 また、self.__class__から新しいインスタンスを作りそのインスタンスを返すと言うメソッドを作る場合もあるかもしれません。 そういうような時にselfの型を返り値の型として指定する方法です。 方法1 - 自分のクラスを返り値の型に指定する これは単純で返り値の型に"User"と指定するだけです。 なぜ文字列なのかというのはUserが見つかりませんと言うエラーが発生してしまうからです。 def update_profile(self) -> "User": ちなみにバージョン3.11では"User"ではなくUserでもできるようになるそうです。 そして3.11でなくても3.7以上ならfrom __future__ import annotationsをやることでUserのように指定することができます。 デメリット これは簡単でわかりやすいのですが、クラスを継承した場合は-> "User"だとその継承したクラスを返すということにならないので、作っていくうちにアウトになってしまいます。 例えばUserクラスを継承したクラスであるMemberクラスを作り、そのクラスはチームのメンバー用のクラスとします。 そのMemberクラスにはそのメンバーのチームの名前であるteamという属性があります この時Memberクラスのメソッドupdate_profileを使いその返り値のteamにアクセスしようとしたとします。 (Member(...).update_profile().team) これはmypyはエラーとします。 なぜなら返り値の型であるUserにはteamがありません。 ですのでエディタの型補完にもteamが表示されません。 こういう時はUnion["User", "継承したクラス名"]のようにtyping.Unionを使い、update_profileメソッドをオーバーライドし、返り値の型を指定してreturn super().update_profile() # type: ignoreをすると一応対処が可能です。 ですがこれだと# type: ignoreを使いますしめんどくさいのと気分悪いです。(個人の問題?) 特に継承して使うクラスとして作ったクラスの場合はとってもめんどくさいです。 ですので継承することがない場合に使うと良いやり方ですね。 方法2 - TypeVarを使う。 ジェネリクスです。 なんか初めて見るとなんだこれとなりそうな感じで実現します。 from typing import TypeVar UserSelf = TypeVar("UserSelf", bound="User") # boundでベースを指定する。 # クラスの上らへんは省略 def update_profile(self: UserSelf) -> UserSelf: selfはUserクラスをベースとしたものを示すUserSelfという型であることを示し、そのUserSelfを返すという感じに指定しています。 TypeVarが具体的にどのように動作するのかはジェネリクスについて調べてから検索してみましょう。 こうすれば方法1のデメリットが解決します。 なのでもしクラスを継承する場合はこの方法を使った方が良いでしょう。 最後に 良いmypyライフを!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Project Euler】Problem 29: べき乗の値

本記事はProjectEulerの「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。 問題 29:べき乗の値 原文 Problem 29: Distinct powers 問題の要約:$2 \leq a, b \leq 100$ のとき$a^b$の値の数を求めよ、ただし重複はかぞえない Pythonでは2重ループはitertools、重複を除くのはsetを使うと簡潔に書けますね。 from itertools import product ab = range(2, 100+1) print(f"Answer : {len(set([a**b for a, b in product(ab,repeat=2)]))}") (開発環境:Google Colab)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Project Euler】Problem 28: 数のらせんの対角線

本記事はProjectEulerの「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。 問題 28:数のらせんの対角線 原文 Problem 28: Number spiral diagonals 問題の要約:図のように1から順番にマスにらせん状に書いて行ったとき1001 x 1001のマスが埋まったときの対角線の数の合計を求めよ なんとなく規則性はつかめそうに思えますが。まず規則通りにマスを埋めるプログラムを書いてみます。 import numpy as np N = 9 vectors = np.array([[-1,0],[0,1],[1,0],[0,-1]]) # direction (0:up, 1:right, 2:down, 3:left ) matrix = np.array([0]*(N**2)).reshape(N,N) # Fill 0s in N x N matrix pos = np.array([(N-1)//2, (N-1)//2]) # Start position dir = 0 # direction index (0:up, 1:right, 2:down, 3:left ) for i in range(1,N**2+1): matrix[pos[0],pos[1]] = i # put the number rpos = pos + vectors[(dir+1)%4] if matrix[rpos[0],rpos[1]] == 0: # if right pos is 0, then turn right dir = (dir+1)%4 # right direction pos = pos + vectors[dir] # next position print(matrix) N=9でできたマス目を表示します。 [[73 74 75 76 77 78 79 80 81] [72 43 44 45 46 47 48 49 50] [71 42 21 22 23 24 25 26 51] [70 41 20 7 8 9 10 27 52] [69 40 19 6 1 2 11 28 53] [68 39 18 5 4 3 12 29 54] [67 38 17 16 15 14 13 30 55] [66 37 36 35 34 33 32 31 56] [65 64 63 62 61 60 59 58 57]] これをじっと見ていると規則性が見えてきます。一辺の長さは2つづつ増えているので、間隔dで4つの角を数字求めて、dを2つ増やすのを繰り返せばいいですね。その合計が答えということです。 N = 9 dg = [1] n, d = 1, 0 for i in range((N-1)//2): d += 2 for i in range(4): n += d dg.append(n) print(sum(dg), dg) #537 [1, 3, 5, 7, 9, 13, 17, 21, 25, 31, 37, 43, 49, 57, 65, 73, 81] (開発環境:Google Colab)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Project Euler】Problem 27: 二次式の素数

本記事はProjectEulerの「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。 問題 27:二次式の素数 原文 Problem 27: Quadratic primes 問題の要約:$|a|,|b|<1000$のとき$n^2+an+b$が$n=0,1,2,3,\dots $のとき連続して素数となる最長の時の$a,b$の積を求めよ まずは全探索で答えを探してみます。すべての$|a|,|b|<1000$で連続する素数の数を求めて最長のものの[連続素数の数、a, b, a*b]を出力します。結果は連続素数が71となりました。 import itertools from sympy import isprime N = 1000 maxConsPrimes = [0,0,0,0] AB = range(-N, N) for a, b in itertools.product(AB,repeat=2): consPrimes = 0 for n in range(0,81): qf = n**2 + a*n + b if not isprime(qf): break else: consPrimes += 1 if consPrimes > maxConsPrimes[0]: #print(f"a = {a}, b = {b}, {consPrimes}") maxConsPrimes = [consPrimes, a, b, a*b] print(maxConsPrimes) オイラーの素数生成式のトリック ここで疑問に思えるのが元のオイラーの素数生成式$n^2\pm n+41$は39個($-$の時は40個)で最長だと思われているのに、簡単に80個や71個の式が見つかるのはへんだと思いませんか? これにはトリックがあります。$x^2+x+41$は2次関数なのでグラフに描くと$x=-1/2$を軸に左右対象の放物線です。したがって$x=0,1,2,3,\dots $で$y$の値が素数になるということは$x=-1,-2,-3,-4\dots $で同じ値の素数になるということになります。 したがってこのグラフを右方向にスライドさせると左半分の部分が$x>0$の領域に入ってくるので見かけ上、連続素数が増えるということです。 グラフを右に$m$だけスライドさせた式$S(m)$は。 S(m)=(x-m)^2+(x-m)+41 \\ =x^2-(2m-1)x+m^2-m+41\\ \\ この時の連続素数の数P(m)は \\ P(0)=39なので \\ P(m)=m+39 (m\leq 40) \\ となりそうです。\\ \\ 最大のP(40)=79となるのは \\  S(40)=x^2-(2\times40-1)x+40^2-40+41 \\ = x^2-79x+1601 \\ となり例題の式と一致します ここで問題に戻ると$|b|<1000$から m^2-m+41<1000 \\ となる最大のmは31になるので \\ a = -(2 \times 31 - 1) = -61 \\ b = 31^2-31+41 = 971 \\ となり解答が筆算で得られました。 (開発環境:Google Colabと筆算)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Google ColaboratoryでStreamlitとReactを接続する。

Streamlitではボタン、フォームなどの標準UIのみで簡単にwebアプリを作ることができます。しかし少し凝ったレイアウトやJavaScriptを使いたい場合にはReactと連携します。 Streamlit+Reactの実装例は公式のComponentsから見ることができます。 各プロジェクト画像 or タイトルからgithubのリポジトリへ行けます。すべてのプロジェクトがReactと連携しているわけではありませんが、プロジェクトと思わしきディレクトリ内にfrontendというディレクトリがあればそのプロジェクトがReactと連携している手掛かりとなります。 チュートリアル React開発環境の構築はCreate React Appで行うと簡単ですが、Streamlit.ioでも同じようなビルド環境が提供されています。 ローカル環境であれば公式通りに進めていけば苦なくチュートリアルは完了するのですが、Google Colaboratory上で完結させるために少しハマった部分があるので残しておきます。 今回はチュートリアルIntroductionのProject Setupまで進めていきたいと思います。 動作 GIF動画 ノートブック Streamlit bridges Python and React メニューバー① > ランタイム > すべてのセルを実行 で再現できるようにしています。 ソース 必要なものをインストール、ダウンロードします。今回はStreamlitとcomponent-templateだけでOKです。 コードセル !pip install streamlit !git clone https://github.com/streamlit/component-template !mv /content/component-template/template $project_path npmコマンドで依存関係をインストールします。my_component/frontend下で行う必要があります。 コードセル !cd $frontend_path &&\ npm install __init__.pyのhttp://localhost:3001をcolabのローカルホストに書き換えます。 コードセル with open(init_py_path, "r") as f: fileText = f.read() after = fileText.replace('"http://localhost:3001"', f'"{getGoogleLocalhost(react_port)}"') with open(init_py_path, "w") as f: f.write(after) streamlit run のあとに npn run startします。 コードセル !streamlit run $init_py_path & sleep 3 && npx localtunnel --port $streamlit_port &\ cd $frontend_path && npm run start your url is: https://***-***-***.loca.ltに接続します。 Clickボタンなど動作を確認できると思います。 おわりに いかがでしたでしょうか。 これでGoogle ColabratoryでのReact開発環境が整い、凝ったスクリプトを搭載したStreamlitプロジェクトもColabratory上で開発できるようになりました。 次回は作ったプロジェクトをgithubと連携しStreamlit.ioへデプロイする一連の流れをGoogle Colabratory上のみでやりたいと思います。 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

pyenvによるPythonのバージョン変更方法 for Mac

参考 概要 Pythonのバージョン切り替え方法について 内容 MacでPythonのバージョンを切り替える場合はpyenvを使用する インストール pyenvのインストール % brew update % brew install pyenv シェルの環境設定 (zshを使用している場合) % echo 'eval "$(pyenv init --path)"' >> ~/.zprofile % echo 'eval "$(pyenv init -)"' >> ~/.zshrc 使用方法 インストール可能なバージョンの確認 % pyenv install --list 指定したバージョンのインストール (今回はバージョン3.7.12をインストール) % pyenv install 3.7.12 インストールしたバージョンの確認 % pyenv versions * system (set by /Users/username/.pyenv/version) 3.7.12 systemは元々入っているPython 3.7.12が今回インストールしたバージョン *(アスタリスク)がついているバージョンが現在適用されている バージョン切り替え % pyenv shell 3.7.12 バージョンの確認 % pyenv versions system * 3.7.12 (set by PYENV_VERSION environment variable) もとに戻すときは % pyenv shell --unset * system (set by /Users/username/.pyenv/version) 3.7.12 補足 Macにはデフォルトでpython2が入っておりコマンド"python ~"ではpython2.xが実行され python 3.xを実行するには"python3 ~"で実行する必要がある。 しかし、pyenvで変更されるのはコマンド"python"の方なのでバージョンを変更したpythonを実行する際は"python ~"で実行する必要がある。 (コマンド"python3"は変更されない) バージョン変更前 % python -V Python 2.7.16 % python3 -V Python 3.8.5 バージョン変更後 % pyenv shell 3.7.12 % python -V Python 3.7.12 % python3 -V Python 3.8.5 以上
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

alpha付き画像の背景を白塗りするやつ

import cv2 img = cv2.cvtColor(cv2.imread("alphaimg.png", -1), cv2.COLOR_BGRA2RGBA) img, mask = img[...,:3], img[...,3:] / 255. img = (img * mask + np.ones(img.shape)*255 * (1. - mask)).astype(np.uint8)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む