他ネットワークのIPが固定されたQNAP NASに接続する
姉妹研究室が他大学に移動する際、NASをいくつかとサーバをいくつか置いて行ってくれた。
サーバは問題なかったが、NASは管理画面をネットワーク接続して表示する仕様を取っていたので困ったことになった。
譲り受けたNASには、姉妹研究室が使っていたネットワーク(今は学校に回収された)で使われていたIPアドレスがそのまま固定されていたのである。
あわや初期化の危機。 ...をなんとか乗り越えられたのでメモ。
Qfinder Proに表示はされているが繋がらない
QNAP NASにはネットワーク内のNASを自動検出するソフトウェア『Qfinder Pro』が用意されている。
とりあえず自分の研究室のルータと譲り受けたNASをLANケーブルで繋いでみると、Qfinder Proでは検出された。
しかし、「サーバからの応答がありません」と言われてしまい、管理画面は開けなかった。
有線LANで接続できた
この状況、DHCPサーバとかがなくてネットワークに繋げない状況と似てるな...と思い、そういう状況下での初期設定手順を検索したら、該当する手順があった。
これはIPアドレスが自動割当されない環境下での初期セットアップの方法なのだが、今回の状況でも同じ方法で接続できた。
- NASとNASセットアップ用のPCをLANケーブルで直接接続
- PCのネットワーク設定を手動にして、IP;169.254.100.101、サブネットマスク255.255.255.0に変更。(これは固定されちゃってるIPアドレスに関わらずこのIPアドレス)
- Qfinder Proのリフレッシュボタンを押す
- NASが表示されたら、ログインを押す
- 管理画面に繋がった
めでたし。
TellusCafe豊橋 に参加したのでメモ
TellusCafe豊橋
概要メモ
- 宇宙産業ビジョン2030の紹介(宇宙ビジョン2030について - 内閣府)
- 宇宙利用産業を活発化させれば宇宙産業を大きくすることになる
- 宇宙利用産業のひとつにリモセン(リモートセンシング技術;対象を遠隔から測定する手段であり、その定義は幅広い。 しかし、狭義には、人工衛星や航空機などから地球表面付近を観測する技術を指すことが多い。)がある
- TELSTAR、宙畑の設立に関わったさくらインターネット株式会社新規事業部の城戸彩乃さんが登壇
- 宇宙衛星データのオープンデータ化の歴史と、日本初のオープン&フリーな衛星データプラットフォームTellusを紹介
- 衛星データは、分散・大容量・高額っていう問題点があった。→さくらインターネットのコンピューティング環境への強みを生かして、様々な衛星データを一箇所に集め、利用するためのクラウド環境を整え、無料で提供する仕組みを作った。それがTellus
- 衛星データは、広域を撮れて、地表にセンサを設置するのに比べて災害等の影響を受けず、周期的で、均質なデータが取れるというメリットが有る
- いろいろな衛星があるが、地球観測衛星が本日のターゲット
- 載せてるセンサは可視光データ以外にもいろいろある(Tellusでも可視光以外のデータも配ってるようす)
- 衛星データの特性がある(常時のデータではなく定期のデータである、とか)
- 活用事例の紹介 例)生産台数を監視しての株価予測 例)お米(青天の霹靂)の収穫時期の推定(一等米比率99%の米「青天の霹靂」に学ぶ、農家のおいしい働き方改革 | 宙畑)
- Tellus活用事例の紹介 (SpaceDataUtilization | 宙畑)
- Tellusユーザ登録(とても簡単)
- ワークショップ:AVNIR-2(ALOSについて - AVNIR-2)のセンサを使って、植生を見てみる
- ワークショップ:観測期間等の条件で絞った衛星データの検索機能を使ってみる
- ワークショップ:オープンデータ(豊橋の妖怪)をTellusにアップロードしてみる(【ゼロからのTellusの使い方】スプレッドシートからGeoJSONを作成する | 宙畑)
感想とかメモ
- 全く新しいデータの活用法を探るより、衛星データの良い特性を活かせるか?という視点で、既にあるセンシング需要に注目したほうがよいかも?と思った(収穫時期の推定の話を受けて)
- JupyterLab(Jupyter notebookの後継機であるWebアプリケーション的IDE。notebookの開発は終了したっぽい。そうだったんだ)
- 「データ選択」のボタンで選択して見れるデータは今の所ひとつの時刻でのデータだけらしい。
- excelgeo(エクセルファイルにある住所から一括で緯度経度を取得できるwebサービス)
- 登壇された城戸さんの「オープンデータを利用した恋人探し」、そういえば以前読ませていただいたことあったなって今思い出した。(オープンデータを利用して理想の恋人は見つかるのか!? 結婚したいOLのクリスマス直前カレシ探し 【前編】 | 宙畑)
- 将来的に、Tellusのクラウドコンピューティング環境でTellusのデータを処理するアルゴリズムとかをユーザが売る(またはシェアする)機能が実装されるらしい。お小遣い稼ぎするためにデータ分析系の能力を鍛えたい。
第4回 Startup Weekend 豊橋 に参加したので感想
少し日が空いてしまったけれど、2019年8月9日〜11日の3日間、Startup Weeked 豊橋 vol.4 に参加したときの印象に残ったことなどを振り返ってまとめた。
※StartupWeekendとは?↓
1分間ピッチのアイディアはウケたけどポシャッた
「超音波メガネ洗浄機をキッチンの洗濯機にしよう」というアイディアを持ち込んだ。このネタはSWに申し込む前から温めていて、顧客もユーザも想定できて市場も広く、物があるので実証実験も簡単、モノからスタートアップを起業する際のデモンストレーションにもなりそうだと思っていた。
会場に向かう道すがらに考えた1分間ピッチのパフォーマンスは思った以上にウケがよく、多くの人から面白いと言って頂けたし、シールもたくさん頂けた。本業で超音波洗浄機を作っているという方からお名刺や資料を頂けたりして、出だしは客観的に見ても順風満帆だったのではないかと思う。
しかし実際には、ピッチのあとのチームメンバー集めの時間でメンバーを1人も集めることができずに「超音波洗濯機」は終わってしまった。最終日の懇談会でも「超音波の人だ〜」と覚えていて頂けたくらいに記憶に残るピッチができていたみたいなので、メンバーを集められなかったのは実は凄く悔しかった。
「何が悪かったのか?」とアドバイスを求めると「押しが弱かったから」「StartupWeekendのネタとしては魅力がなかったのでは?」「アイディアが完成されすぎちゃって逆に何したら良いか分からなかったのでは?」といった助言をもらった。思い返すと「私のチームにはあなたが必要です」と参加者を口説き落とすことができていなかったし、ピッチでもアイディアの説明はしたけれどビジネスモデルとかSWでやりたいことの具体的な話はできていなかった。「人を口説くのも慣れだから」と励まして頂いたので、そういう機会を得て少しずつ慣れていこうと思う。
迷走ではないピボットを経験できた
私達のチームが最終ピッチで発表したビジネスは『各家庭に応じたローリングストック習慣を提供する』サービスである。思い返せばこのサービス、初日のピッチ内容と変わらないのは「食材消費サイクルの管理に関する面倒を解消する」という点だけだ。
消費期限を管理して食材の廃棄ロスを減らすという初日のアイディアから、食品廃棄問題を解決したい企業を顧客にする二日目前半のアイディアに変わり、さらに、ローリングストック法の習慣化に苦しむ一般家庭を顧客にするという大胆なピボットを行った後、二日目夜に発見した既存サービスとの差別化を意識した結果、三日目の午前中にアレルギー対応するローリングストック支援サービスという最終ピッチでのアイディアに終着した。顧客もペルソナもサービス内容も何度も変更を行ったが、どの時点でも全員の合意がとれていたのは、しっかり議論を行えていたからではないかと思う。
二日目後半の大きなピボットのとき、私は食品廃棄問題を捨てるという判断にどうしても納得がいかなかった。進路を大きく変える判断だと感じたから、腑に落ちないまま進むのが嫌で、何故捨てる必要があるのかとかなり食い下がってメンバーに聞いた覚えがある。正回答がある問題ではないのだ、今思えば他のメンバーだって私にそんなふうに詰問される筋合いはないだろうに、メンバーは私が納得のいくまで根気よく言葉を交わしてくれた。誰もが正解を知らない中で、議論によって進む道を決めていくという感覚が、なんだか妙に印象に残った。迷走とピボットの違いってなんだろう。その疑問を解くピースのひとつを、今回手に入れることができた気がする。
仲間を信じて自分の常識を捨てたら、いつもと全く違う景色が見えた
私達のチームメンバーは皆個性がバラバラだった。そして今回は、そのバラバラさが良い意味で発揮されていた。
2日目の夜、私達のチームはサービスの需要を測るために実際に通販サイトを作り、一晩だけだが実際に販売してみる試みをした(結局一つも売れなかったが)。その案が動き出した時、実は内心「まだ起業した訳でもないのに実際に売ったりして大丈夫なんだろうか」と思っていた。しかし、メンバーの中に個人で通販サイトを運営している人がいたので、その人についていく形で試行販売に乗り切ることができた。異なる経験を持つメンバーがいて、自分の常識を捨ててメンバーを信じることができたからこそ、自分一人では決してできなかったこの試みが実行できたのだと思う。
また、社会人メンバーがいたからこそできたこともある。それは、自分たちのビジネスモデルについて多くの人の意見を聞くという試みだ。二日間を通して、コーチ全員はもちろん、遊びに来てくれた他のチームメンバーや運営サイドの人たち全員に対しても、社会人メンバー2人は積極的にチームのビジネスモデルを説明して意見を求めた。時には作業の手を止めてまでディスカッションを優先する姿勢に、実は最初の頃は「話してばかりいないで手を動かしたほうが良いのではないか」と思っていた。しかし、後になってみると、そうして客観的で多角的な意見を常に取り入れ続けることが、私達のビジネスモデルを練り上げてくれたのだと分かった。
ディスカッションのやり方も勉強になった。訪問者がいれば、まず聞いてくださいとお願いし、丁寧に説明する。次に意見を全部聞く。このとき、意見を引き出すための質問はしても、意見をねじ伏せるための質問や反対意見は述べない。訪問客が去ったあとで、必要があればメンバー内で議論を行う。このルーチンを、訪問客をトリガーに機械的に繰り返していく。私は未完成のものを他人に見せることに強い苦手意識を持っていて、それは研究を進めたり論文を作ったりする上で大きな障害になっているなと度々感じていた。メンバーから学んだこの姿勢は、私の苦手意識を克服する手がかりになると思った。
私達のメンバーは皆バラバラの個性を持っていたけれど、それぞれの持ち味が組み合わさったことで、一人一人ではできない多くのことができた。そんなふうに「いい感じ」なチームであれたのも、全員がお互いにリスペクトの心を持てていたからかなと思った。
StartupWeekend、また参加したい
初めて参加したのは2017年2月頃、当時は学部4年生だったと思う。第2回と第3回は見送って、今回の第4回に再挑戦として参加した。
起業には興味がないが、エンジニアで食べていきたいという思いがあるので、ニーズや顧客を捉えたモノ作りのフレームワークを体得したいという目的で参加している。
実際に参加すると、モノ作りのフレームワーク以外にも、本当に多くのことを学べる。二回参加してみて、参加時のライフステージや本業の内容によっても、得られる学びは変わってくるなと思った。
来年度から社会人になる。社会人1年目、3年目、10年目など、立場が変わっていく中で、また何度かStartupWeekendに参加してみたいと思う。
(起業に興味ないのに起業イベントに参加する迷惑おばさんと化す未来が見える...)
感謝
素晴らしい機会を与え支えてくださった運営の方々、たくさんのアドバイスと励ましをくださったコーチの方々、一緒に楽しく参加してくださった参加者の皆様、本当にありがとうございました。
圧倒的感謝。
外部モジュールのlogging.debug()を画面&ファイル出力するにはrootLoggerに対してレベルとハンドラーの設定を追加すればいい
背景
Pythonのword2vecモジュール「gensim.models.word2vec」を用いて自前の単語分散表現word2vecを得ようとした。
こちらの記事
【Python】Word2Vecの使い方 - Qiita
を参考にしたら、とてもスムーズに学習・類似単語表示の機能を実装できたのだが、
word2vecの学習過程を表示する機能を実装する際に、logging
への理解が浅かったことが原因で大分ハマってしまった。
ハマりポイントは以下。
- メインプログラムのデバッグ文用に自前の
logger
を設置していて、logger.debug()
等の結果をファイル出力&画面出力できている。 - しかし、
logger
は設定できてるはずなのに、word2vecの学習過程ログは出力されない。なんでだろう? - word2vecの学習過程ログをファイルに出力したい。けど、
basicConfig()
ではファイル出力と画面出力を同時設定できない仕様らしい(←誤解)、どうすればいいんだろう。
上記ハマりポイントについて、順番に解消していく。
gensim.models.word2vec
のlogger
は「ハンドラーが設定されていないから」画面に現れない
本家のプログラムを読むと分かるが、gensim.models.word2vec
のロギングシステムは、
- 【グローバル変数】として
logging
をインスタンス化logger = logging.getLogger(__name__)
- 【関数
Word2Vec()
内】でlogger.info()
等してログに書き出し - 【
if __name__ == '__main__'
内】でlogging.basicConfig()
してハンドラーやレベルを設定
という形になっている。
このうち、外部からfrom gensim.models import word2vec; word2vec.Word2Vec()
などとしてWord2Vec()
関数を呼び出した場合、実行されるのは1番目と2番目の項目だけなので、logging
はインスタンス化されただけでハンドラーやレベルの設定がされていない状態となるのだ。
学習過程ログはlogger.debug()
及びlogger.info()
を用いて書き出すように実装されているので、これでは出力されない、ということが分かる。
loggingの使い方おさらい
上の説明で「OK分かったよ」ってなれる人は良いのだけれど、
logging
への理解が浅かった昨日までの私なら分からなかっただろうと思うので、ここで簡単にloggingの挙動のおさらいをしておく。
logging.debug()
を標準出力に出力するためにはレベルの設定が必要
logging
のロギングシステムには、緊急度で4つのレベル分けがされている。
例えば以下のプログラムだと、
""" 全レベルのログを出力しようとしてみる。できない。 """ import logging logging.debug('でばっぐtest1') logging.info('いんふぉtest1') logging.warning('わーにんぐtest1') logging.error('えらーtest1')
WARNING:root:わーにんぐtest1 ERROR:root:えらーtest1
DEBUGとINFOのログが出力されない。
これはなぜかというと、ルートロガーに対してハンドラが未定義だったために自動でlogging.basicConfig()
が呼ばれ、
logging.basicConfig()
のデフォルトの設定ではログ出力レベルが「WARNING以上」に設定されているからである。
ついでに、書式もデフォルトの書式'%(levelname)s:%(name)s:%(message)s'
で出力されている。
関数 debug(), info(), warning(), error(), critical() は、ルートロガーにハンドラが定義されていない場合に自動的に basicConfig() を呼び出します。
出典:logging --- Python 用ロギング機能 — Python 3.7.4 ドキュメント
したがって、DEBUGやINFOなどWARNING未満のレベルのメッセージを出力したい場合には、その旨を設定してやる必要がある。
設定にはlogging.basicConfig()
を使う。
""" ルートロガーにレベルとフォーマットの設定をした。 """ import logging format_str = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig( format=format_str, level=logging.DEBUG ) logging.debug('でばっぐtest1') logging.info('いんふぉtest1') logging.warning('わーにんぐtest1') logging.error('えらーtest1')
2019-08-22 00:10:46,663 - root - DEBUG - でばっぐtest1 2019-08-22 00:10:46,664 - root - INFO - いんふぉtest1 2019-08-22 00:10:46,664 - root - WARNING - わーにんぐtest1 2019-08-22 00:10:46,664 - root - ERROR - えらーtest1
全レベルのメッセージが標準出力に出力された。
…rootlogger = logging.getLogger()
してrootLoggerをインスタンス化して設定を行う方法も思いついたけどなんかあんまりよくない気配がするので今回は触れない。
インスタンスlogger = logging.getLogger(__name__)
のハンドラーやレベルを設定するには
logging
は木構造になっていて、ルートロガーの設定が 子ロガー にも継がれる。
だから、これまでと同様にルートロガーにレベルとハンドラーを設定するだけでいい。
""" ルートロガーに設定すれば、子ロガーもその設定を継ぐ """ import logging format_str = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig( format=format_str, level=logging.DEBUG ) logging.debug('でばっぐtest1') logging.info('いんふぉtest1') logging.warning('わーにんぐtest1') logging.error('えらーtest1') logger = logging.getLogger(__name__) logger.debug('でばっぐtest1') logger.info('いんふぉtest1') logger.warning('わーにんぐtest1') logger.error('えらーtest1')
2019-08-22 00:22:05,722 - root - DEBUG - でばっぐtest1 2019-08-22 00:22:05,722 - root - INFO - いんふぉtest1 2019-08-22 00:22:05,722 - root - WARNING - わーにんぐtest1 2019-08-22 00:22:05,722 - root - ERROR - えらーtest1 2019-08-22 00:22:05,722 - __main__ - DEBUG - でばっぐtest1 2019-08-22 00:22:05,722 - __main__ - INFO - いんふぉtest1 2019-08-22 00:22:05,722 - __main__ - WARNING - わーにんぐtest1 2019-08-22 00:22:05,723 - __main__ - ERROR - えらーtest1
ルートロガーに対してレベルやフォーマットの設定を行っただけで、mainと名付けた 子ロガー の全レベルのログメッセージが出力されていることが確認できる。
ちなみに、子ロガーに対してルートロガーと異なる設定を行うこともできる。
""" ルートロガーと子ロガーで異なる設定を行うこともできる """ import logging format_str = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' # ルートロガーの設定 logging.basicConfig( format=format_str, level=logging.DEBUG ) handler_format = Formatter(format_str) # 標準出力 stream_handler = StreamHandler() stream_handler.setFormatter(handler_format) logger = getLogger(__name__) # 子ロガーの設定 logger.setLevel(logging.INFO) logger.addHandler(stream_handler) logger.propagate = False logging.debug('でばっぐtest1') logging.info('いんふぉtest1') logging.warning('わーにんぐtest1') logging.error('えらーtest1') logger.debug('でばっぐtest1') logger.info('いんふぉtest1') logger.warning('わーにんぐtest1') logger.error('えらーtest1')
2019-08-22 00:28:52,315 - root - DEBUG - でばっぐtest1 2019-08-22 00:28:52,315 - root - INFO - いんふぉtest1 2019-08-22 00:28:52,315 - root - WARNING - わーにんぐtest1 2019-08-22 00:28:52,315 - root - ERROR - えらーtest1 2019-08-22 00:28:52,315 - __main__ - INFO - いんふぉtest1 2019-08-22 00:28:52,315 - __main__ - WARNING - わーにんぐtest1 2019-08-22 00:28:52,316 - __main__ - ERROR - えらーtest1
ルートロガーは全レベル、子ロガーはINFO以上のレベルのメッセージを表示していることが分かる。
logging.basicConfig()
してルートロガーにハンドラーを設定すれば、gensim.models.word2vec
のlogger
を画面出力させられる
さて、gensim.models.word2vec
のlogging
のインスタンスlogger
にハンドラーが設定されていないのが問題なら、ハンドラーを設定してしまえば解決するはずである。
(´-`).。oO((インスタンスにハンドラーを追加するって、pip install
したgensim.models.word2vec.py
を弄るってこと?))
(´v`).。oO((ちょっと背徳的でそれもいいねぇ))
けど、gensim.models.word2vec
のlogger
にハンドラーを追加するには、インスタンス自体にハンドラーを追加する必要はないのです。
なぜなら、そう、logging
は階層構造なので、ルートロガーに対してハンドラーを設定すればその子ロガーにも設定が継がれるから。
この法則は、外部からファイルを読み込んだ場合にも適応される。
ちなみに外部から呼んだ場合は、__name__
の中身がモジュール名になる。
""" test1.py ハンドラー未定義のloggerをもつ。gensim.models.word2vecの立場 """ import logging def print_debug(): logger = logging.getLogger(__name__) logger.debug('でばっぐtest1') logger.info('いんふぉtest1') logger.warning('わーにんぐtest1') logger.error('えらーtest1')
""" test2.py ルートロガーを設定した。自前のメインプログラムの立場 """ from logging import getLogger, basicConfig, DEBUG import test1 def set_rootLogger(): format_str = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' basicConfig( format=format_str, level=DEBUG ) def print_debug(): logger = getLogger(__name__) logger.debug('でばっぐtest2') logger.info('いんふぉtest2') logger.warning('わーにんぐtest2') logger.error('えらーtest2') if __name__ == '__main__': set_rootLogger() print_debug() test1.print_debug()
$ python3 test2.py 2019-08-22 00:41:13,209 - __main__ - DEBUG - でばっぐtest2 2019-08-22 00:41:13,209 - __main__ - INFO - いんふぉtest2 2019-08-22 00:41:13,209 - __main__ - WARNING - わーにんぐtest2 2019-08-22 00:41:13,210 - __main__ - ERROR - えらーtest2 2019-08-22 00:41:13,210 - test1 - DEBUG - でばっぐtest1 2019-08-22 00:41:13,210 - test1 - INFO - いんふぉtest1 2019-08-22 00:41:13,210 - test1 - WARNING - わーにんぐtest1 2019-08-22 00:41:13,210 - test1 - ERROR - えらーtest1
そういうわけで、最初に述べた参考記事でも紹介されている通り、logging.basicConfig()
をしてルートロガーにハンドラーを設定すれば、gensim.models.word2vec
のlogger
を画面出力させられる。
from gensim.models import word2vec import logging logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) # 以下、word2vecの学習に関するプログラムが続く... # ...
handlersオプションを使えば、標準出力とファイル出力の両方にログを出力できる
ここまでに紹介したbasicConfig()
の設定では、標準出力には出力できるがファイルには出力できない。
両方出力したい、というときには、以下のようにする。
from logging import getLogger, basicConfig, DEBUG, StreamHandler, FileHandler, Formatter logf = 'test1.log' format_str = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' handler_format = Formatter(format_str) # 標準出力 stream_handler = StreamHandler() stream_handler.setFormatter(handler_format) # ファイル出力 file_handler = FileHandler(logf, 'a') file_handler.setFormatter(handler_format) logging.basicConfig( handlers=[stream_handler, file_handler], level=logging.DEBUG ) logger = getLogger(__name__) logger.debug('でばっぐtest1') logger.info('いんふぉtest1') logger.warning('わーにんぐtest1') logger.error('えらーtest1')
まとめ
gensim.models.word2vecの学習過程ログを画面&ファイル出力するにはrootLoggerに対してレベルとハンドラーの設定を追加すればいい
感想
ロギングシステムを実装しようと思って勉強した事はあったけど、 他者が作った他のモジュールのロギングシステムを使おうとしたのは初めてだったので、とても勉強になった。