beautifulsoupかゆいところに手が届くリスト
tl;dr
覚書
python3.6
beautifulsoup4==4.7.1
タグ取り出し
- find_all()は独自型じゃなくてlistで返す
- タグでfindしたあとそのタグ自体を消したいときは.string
(ex:
検索元タグあり = soup.find('p')
検索元タグあり = soup.find('p').string
)
bs4.element.Tag型が持ってる属性だからfind_all()で取得したものに全部適応するときはmap()とかワンテンポ置く必要ある
逐一追記する
GPUを無料で使う方法の模索
LINEBot&Clova Advent Calendar 2018(12/20)
こんにちは。
近頃めちゃめちゃ寒いですね〜〜
アドベントカレンダーも今日で20日目です!
私は正直最近LINEbotに全く触れておらずそれ以外のことでてんてこ舞いです。なので、やってる分野とうまく知見を共有できないかなと思い、私が少しプレゼンした際の機械学習の資料を貼ろうと思います。
これは半教師あり学習というMLの一つで、前半は説明要素が多いですが後半にテーマである「bot開発で役に立つAPIやOSSの紹介、かんたんな非公式APIの作り方」がちょくちょく出てきます!!
解説を逐一増やしていこうと思います。
わからない点があればお気軽にどうぞ!
質が低いのはご了承ください笑
ではまた追記します!(日付まにあったかな…??)
【OS X】wgetコマンドが使えない際の解決方法(2019)
osxはhomebrewがあります。
$ brew install wget
で一発!!
というわけには行かないことが多いです
$ wget -h
で動作確認が行えますが
dyld: Library not loaded: /usr/local/opt/gettext/lib/libintl.8.dylib Referenced from: /usr/local/bin/wget Reason: image not found Abort trap: 6
怒られます。
これはOSXでデフォで入っているgettextライブラリの問題です。 PATHを弄るより、homebrewに頼る方が安全です。
$ brew uninstall --force gettext $ brew install gettext gettext is keg-only, which means it was not symlinked into /usr/local, because macOS provides the BSD gettext library & some software gets confused if both are in the library path. If you need to have gettext first in your PATH run: echo 'export PATH="/usr/local/opt/gettext/bin:$PATH"' >> ~/.bash_profile For compilers to find gettext you may need to set: export LDFLAGS="-L/usr/local/opt/gettext/lib" export CPPFLAGS="-I/usr/local/opt/gettext/include"
PATHをイジってもいいですがちゃんと$ source ~/.${シェルのプロファイル}
をしましょう
gettextのインスコが終わったら
$ brew uninstall --force wget $ brew install wget
$ wget -h GNU Wget 1.19.5, 非対話的ネットワーク転送ソフト 使い方: wget [オプション]... [URL]... 長いオプションで不可欠な引数は短いオプションでも不可欠です。 スタートアップ: -V, --version バージョン情報を表示して終了する -h, --help このヘルプを表示する -b, --background スタート後にバックグラウンドに移行する -e, --execute=COMMAND `.wgetrc'形式のコマンドを実行する ログと入力ファイル: -o, --output-file=FILE ログを FILE に出力する -a, --append-output=FILE メッセージを FILE に追記する -q, --quiet 何も出力しない -v, --verbose 冗長な出力をする (デフォルト) -nv, --no-verbose 冗長ではなくする --report-speed=TYPE 帯域幅を TYPE で出力します。TYPE は 'bits' が指定できます。 -i, --input-file=FILE FILE の中に指定された URL をダウンロードする -F, --force-html 入力ファイルを HTML として扱う -B, --base=URL HTML で入力されたファイル(-i -F)のリンクを 指定した URL の相対 URL として扱う --config=FILE 設定ファイルを指定する --no-config 設定ファイルを読みこまない --rejected-log=FILE 拒否された理由をログ FILE に保存する ダウンロード: -t, --tries=NUMBER リトライ回数の上限を指定 (0 は無制限). --retry-connrefused 接続を拒否されてもリトライする --retry-on-http-error=ERRORS comma-separated list of HTTP errors to retry -O, --output-document=FILE FILE に文書を書きこむ -nc, --no-clobber 存在しているファイルをダウンロードで上書きしない --no-netrc don't try to obtain credentials from .netrc -c, --continue 部分的にダウンロードしたファイルの続きから始める --start-pos=OFFSET OFFSET からダウンロードを開始する --progress=TYPE 進行表示ゲージの種類を TYPE に指定する --show-progress どのモードでも進捗バーを表示する -N, --timestamping ローカルにあるファイルよりも新しいファイルだけ取得する --no-if-modified-since タイムスタンプモードの時に、 if-modified-since get リクエストを使わない --no-use-server-timestamps ローカル側のファイルのタイムスタンプに サーバのものを使わない -S, --server-response サーバの応答を表示する --spider 何もダウンロードしない -T, --timeout=SECONDS 全てのタイムアウトを SECONDS 秒に設定する --dns-timeout=SECS DNS 問い合わせのタイムアウトを SECS 秒に設定する --connect-timeout=SECS 接続タイムアウトを SECS 秒に設定する --read-timeout=SECS 読み込みタイムアウトを SECS 秒に設定する -w, --wait=SECONDS ダウンロード毎に SECONDS 秒待つ --waitretry=SECONDS リトライ毎に 1〜SECONDS 秒待つ --random-wait ダウンロード毎に 0.5*WAIT〜1.5*WAIT 秒待つ --no-proxy プロクシを使わない -Q, --quota=NUMBER ダウンロードするバイト数の上限を指定する --bind-address=ADDRESS ローカルアドレスとして ADDRESS (ホスト名か IP) を使う --limit-rate=RATE ダウンロード速度を RATE に制限する --no-dns-cache DNS の問い合わせ結果をキャッシュしない --restrict-file-names=OS OS が許しているファイル名に制限する --ignore-case ファイル名/ディレクトリ名の比較で大文字小文字を無視する -4, --inet4-only IPv4 だけを使う -6, --inet6-only IPv6 だけを使う --prefer-family=FAMILY 指定したファミリ(IPv6, IPv4, none)で最初に接続する --user=USER ftp, http のユーザ名を指定する --password=PASS ftp, http のパスワードを指定する --ask-password パスワードを別途入力する --use-askpass=COMMAND 認証情報(ユーザ名とパスワード)を取得するハンドラを指定します。 COMMAND が指定されない場合は、 環境変数 WGET_ASKPASS か SSH_ASKPASS が 使われます。 --no-iri IRI サポートを使わない --local-encoding=ENC 指定した ENC を IRI のローカルエンコーディングにする --remote-encoding=ENC 指定した ENC をデフォルトのリモートエンコーディングにする --unlink 上書きする前にファイルを削除する --no-xattr 拡張ファイル属性へのメタデータ保存を無効にする ディレクトリ: -nd, --no-directories ディレクトリを作らない -x, --force-directories ディレクトリを強制的に作る -nH, --no-host-directories ホスト名のディレクトリを作らない --protocol-directories プロトコル名のディレクトリを作る -P, --directory-prefix=PREFIX ファイルを PREFIX/ 以下に保存する --cut-dirs=NUMBER リモートディレクトリ名の NUMBER 階層分を無視する HTTP オプション: --http-user=USER http ユーザ名として USER を使う --http-password=PASS http パスワードとして PASS を使う --no-cache サーバがキャッシュしたデータを許可しない --default-page=NAME デフォルトのページ名を NAME に変更します 通常は `index.html' です -E, --adjust-extension HTML/CSS 文書は適切な拡張子で保存する --ignore-length `Content-Length' ヘッダを無視する --header=STRING 送信するヘッダに STRING を追加する --compression=TYPE choose compression, one of auto, gzip and none. (default: none) --max-redirect ページで許可する最大転送回数 --proxy-user=USER プロクシユーザ名として USER を使う --proxy-password=PASS プロクシパスワードとして PASS を使う --referer=URL Referer を URL に設定する --save-headers HTTP のヘッダをファイルに保存する -U, --user-agent=AGENT User-Agent として Wget/VERSION ではなく AGENT を使う --no-http-keep-alive HTTP の keep-alive (持続的接続) 機能を使わない --no-cookies クッキーを使わない --load-cookies=FILE クッキーを FILE から読みこむ --save-cookies=FILE クッキーを FILE に保存する --keep-session-cookies セッションだけで用いるクッキーを保持する --post-data=STRING POST メソッドを用いて STRING を送信する --post-file=FILE POST メソッドを用いて FILE の中味を送信する --method=HTTPMethod "HTTPMethod" をヘッダのメソッドとして使います --body-data=STRING STRING をデータとして送る。--method を指定してください。 --body-file=FILE ファイルの中味を送る。--method を指定してください。 --content-disposition Content-Disposition ヘッダがあれば ローカルのファイル名として用いる (実験的) --content-on-error サーバエラー時に受信した内容を出力する --auth-no-challenge サーバからのチャレンジを待たずに、 Basic認証の情報を送信します。 HTTPS (SSL/TLS) オプション: --secure-protocol=PR choose secure protocol, one of auto, SSLv2, SSLv3, TLSv1, TLSv1_1, TLSv1_2 and PFS --https-only 安全な HTTPS のリンクだけたどる --no-check-certificate サーバ証明書を検証しない --certificate=FILE クライアント証明書として FILE を使う --certificate-type=TYPE クライアント証明書の種類を TYPE (PEM, DER) に設定する --private-key=FILE 秘密鍵として FILE を使う --private-key-type=TYPE 秘密鍵の種類を TYPE (PEM, DER) に設定する --ca-certificate=FILE CA 証明書として FILE を使う --ca-directory=DIR CA のハッシュリストが保持されているディレクトリを指定する --crl-file=FILE CRL ファイルを指定する --pinnedpubkey=FILE/HASHES 公開鍵 (PEM/DER) ファイル、もしくは、base64でエンコードした sha256ハッシュ値(sha256//で始まりセミコロン区切り)を指定して、 相手を認証します。 --random-file=FILE SSL PRNG の初期化データに使うファイルを指定する --egd-file=FILE EGD ソケットとして FILE を使う --ciphers=STR Set the priority string (GnuTLS) or cipher list string (OpenSSL) directly. Use with care. This option overrides --secure-protocol. The format and syntax of this string depend on the specific SSL/TLS engine. HSTS オプション: --no-hsts HSTS を使わない --hsts-file HSTS データベースのパス (デフォルトを上書き) FTP オプション: --ftp-user=USER ftp ユーザとして USER を使う --ftp-password=PASS ftp パスワードとして PASS を使う --no-remove-listing `.listing' ファイルを削除しない --no-glob FTP ファイル名のグロブを無効にする --no-passive-ftp "passive" 転送モードを使わない --preserve-permissions リモートのファイルパーミッションを保存する --retr-symlinks 再帰取得中に、シンボリックリンクでリンクされた先のファイルを取得する FTPS オプション: --ftps-implicit implicit FTPS を使う (デフォルトポートは 990) --ftps-resume-ssl 制御接続で開始した SSL/TLS セッションを データ接続で再開する --ftps-clear-data-connection 制御チャネルだけ暗号化する(データは平文になる) --ftps-fallback-to-ftp サーバが FTPS に対応していない場合は FTP にする WARC オプション: --warc-file=FILENAME リクエスト/レスポンスデータを .warc.gz ファイルに保存する --warc-header=STRING warcinfo record に STRING を追加する --warc-max-size=NUMBER WARC ファイルのサイズの最大値を NUMBER に設定する --warc-cdx CDX インデックスファイルを書く --warc-dedup=FILENAME 指定した CDX ファイルに載っている record は保存しない --no-warc-compression WARC ファイルを GZIP で圧縮しない --no-warc-digests SHA1 ダイジェストを計算しない --no-warc-keep-log WARC record にログファイルを保存しない --warc-tempdir=DIRECTORY WARC 書込時の一時ファイルを置くディレクトリを指定する 再帰ダウンロード: -r, --recursive 再帰ダウンロードを行う -l, --level=NUMBER 再帰時の階層の最大の深さを NUMBER に設定する (0 で無制限) --delete-after ダウンロード終了後、ダウンロードしたファイルを削除する -k, --convert-links HTML や CSS 中のリンクをローカルを指すように変更する --convert-file-only URLのファイル名部分だけ変換する (いわゆるbasename) --backups=N ファイルに書きこむ時に N ファイルのバックアップをローテーションさせる -K, --backup-converted リンク変換前のファイルを .orig として保存する -m, --mirror -N -r -l 0 --no-remove-listing の省略形 -p, --page-requisites HTML を表示するのに必要な全ての画像等も取得する --strict-comments HTML 中のコメントの処理を厳密にする 再帰ダウンロード時のフィルタ: -A, --accept=LIST ダウンロードする拡張子をコンマ区切りで指定する -R, --reject=LIST ダウンロードしない拡張子をコンマ区切りで指定する --accept-regex=REGEX 許容する URL の正規表現を指定する --reject-regex=REGEX 拒否する URL の正規表現を指定する --regex-type=TYPE 正規表現のタイプ (posix) -D, --domains=LIST ダウンロードするドメインをコンマ区切りで指定する --exclude-domains=LIST ダウンロードしないドメインをコンマ区切りで指定する --follow-ftp HTML 文書中の FTP リンクも取得対象にする --follow-tags=LIST 取得対象にするタグ名をコンマ区切りで指定する --ignore-tags=LIST 取得対象にしないタグ名をコンマ区切りで指定する -H, --span-hosts 再帰中に別のホストもダウンロード対象にする -L, --relative 相対リンクだけ取得対象にする -I, --include-directories=LIST 取得対象にするディレクトリを指定する --trust-server-names ファイル名としてリダイレクト先のURLの最後の部分を使う -X, --exclude-directories=LIST 取得対象にしないディレクトリを指定する -np, --no-parent 親ディレクトリを取得対象にしない Email bug reports, questions, discussions to <bug-wget@gnu.org> and/or open issues at https://savannah.gnu.org/bugs/?func=additem&group=wget.
やったぜ!!
おわり
【深層学習】データセットを渡すとフルオートで対立的画像を生成してラベルと一緒に返すプログラム
対立的画像生成アルゴリズムをyamlから指定すると全自動で行ってくれます。
import numpy as np import glob import sys import os from keras.preprocessing.image import load_img, img_to_array, array_to_img, save_img , ImageDataGenerator from keras.utils import to_categorical # Generate conflicting images fully automatically :) # [usage] # 2 step (Please set param.yaml in advance.) # # instance = OpponentImage(Kernel): # instance.return_datafile() # # too easy ! :) class Kernel(): def __init__(self): datas_path = '../../data/img/' datas_dir = os.listdir(path=datas_path) if '.DS_Store' in datas_dir: datas_dir.remove('.DS_Store') try: self.labels = list(map(lambda label: label.split('_')[0], datas_dir)) self.params = self.read_yaml('../../param.yml') self.datas = glob.glob(datas_path + datas_dir[0] + '/*.{}'.format(self.params['crawler']['ext'])) self.datas.sort() except Exception as e: sys.stderr.write(str(e)) print() exit() def data_split(self, validation=False): test_num = int(len(self.datas) * self.params['ml']['test_data_rate']) train_num = len(self.datas) - test_num self.x_train_raw = self.datas[:train_num] self.x_test_raw = self.datas[-test_num:] def data_preprocess_basic(self, gray=True, size=(100,100), precision=np.float16): self.x_train = [] self.y_train = [] self.x_test = [] self.y_test = [] size = [self.params['ml']['img_size_xy']]*2 if not self.params['ml']['img_size_xy'] == None else size for label, valid in enumerate([self.x_train_raw, self.x_test_raw]): for img_path in valid: try: img = load_img(img_path, grayscale=gray, target_size=tuple(size)) img_bin = img_to_array(img) # data_container[label].append(img_bin) if label == 0: self.x_train.append(img_bin) self.y_train.append([0]) elif label == 1: self.x_test.append(img_bin) self.y_test.append([0]) except: print('cant preprocessed image.[{}]'.format(img_path)) continue else: print('encoded img.[{}]'.format(img_path)) # self.x_train = list(map(lambda img_bin: np.float16(img_bin)/255, self.x_train)) # self.x_test = list(map(lambda img_bin: np.float16(img_bin) / 255, self.x_test)) self.x_train = list(map(lambda img_bin: np.ravel(precision(img_bin) / 255), self.x_train)) self.x_test = list(map(lambda img_bin: np.ravel(precision(img_bin) / 255), self.x_test)) print('data shape {}'.format(self.x_train[0].shape)) print('train {} test {}'.format(len(self.x_train), len(self.x_test))) def labeling(self, one_hot=True): pass def read_yaml(self, uri): import yaml try: with open(uri, 'r') as d: param_dict = yaml.load(d) except Exception as err: sys.stdout.write(str(err)) return return param_dict from PIL import Image, ImageChops, ImageOps, ImageDraw #generate image of opponent class OpponentImage(Kernel): def __init__(self): Kernel.__init__(self) self.data_split() self.data_preprocess_basic() self.ancestors = [self.x_train, self.x_test] self.ancestors_label = [self.y_train, self.y_test] self.decay = self.params['oppoimg']['decay'] self.mode = self.params['oppoimg']['mode'] # self.__gc_superclassvals() self.datas = self.make_fuzzyimg(decay=self.decay, effect=self.mode) def make_fuzzyimg(self, decay, effect): import effect_func as ef e_dict = { 's_random': lambda x: ef.simple_random(x), 'swap': lambda x: ef.swap(x), 'as_random': lambda x: ef.ancestral_scale_random(x), 'as_randomv2': lambda x: ef.ancestral_scale_random_v2(x) } for i, img_bins in enumerate(self.ancestors): flat_img_bins = [*map(lambda img_bin: np.ravel(img_bin), img_bins)] for img_count, flat_img_bin in enumerate(flat_img_bins): # print(flat_img_bin, flat_img_bin.shape) # break try: effected_bin = e_dict[effect](flat_img_bin) # self.ancestors[i].append(effected_bin) # self.ancestors_label[i].append([1]) if i == 0: self.x_train.append(effected_bin) self.y_train.append([1]) elif i == 1: self.x_test.append(effected_bin) self.y_test.append([1]) except: print('cant generate fuzzyimg.') continue else: print('generated fuzzyimg.{}'.format(img_count+1)) print('fuzzy mode {}'.format(effect)) # self.__test_show(self.ancestors[0][150]) def anal_ances(self): pass def return_datafiles(self): self.y_train = to_categorical(self.y_train, num_classes=2) self.y_test = to_categorical(self.y_test, num_classes=2) return (self.x_train, self.x_test, self.y_train, self.x_test) def __test_show(self, np_img): import matplotlib.pyplot as plt ex_img = array_to_img(np_img.reshape(100,100,1)) ex_img.save('test.png') def __gc_superclassvals(self): import gc rm_ivals = [ival for ival in list(self.__dict__.keys()) if ival is not 'ancestors'] for rm_ival in rm_ivals: try: del rm_ival except Exception as e: print(e) exit() # kernel test if __name__ == '__main__': pass # k = Kernel() # k.data_split() # k.data_preprocess_basic() # oppi = OpponentImage() # datasets = oppi.return_datafiles()
# 対立的画像生成アルゴリズム群(模索中) def simple_random(img_bin): import random import numpy as np # maxis = [] # minis = [] # li = img_bin.tolist() # li_proto = li[:] # random.shuffle(li) # print(li) # re_bin = np.array(li) # for tensor in range(len(img_bin)-1): # maxis.append(img_bin[tensor].argmax()) # minis.append(img_bin[tensor].argmin()) # for tensor in range(len(img_bin)): # img_bin[tensor] = random.random(img_bin[tensor]) # print(img_bin[0]) # print(type(img_bin)) # print(maxis) # print(minis) print(img_bin) re_bin = np.random.permutation(img_bin) print(re_bin) return re_bin def ancestral_scale_random(img_bin): pass def ancestral_scale_random_v2(img_bin): pass def swap(img_bin): pass
これはカーネルファイルなので使いやすいAPIを前面に設置し、カスタマイズ性を向上させています。
全体としては各アプリケーションを独立させ、カーネルの上にAPIを設置し、そのAPIを積み木のように簡単に実行ファイルに組み立て、誰でも簡単に扱える設計となっております。
おわりに
形になったらESSLの全体アーキテクチャを公開したいです。
2値分類における完全片ラベル教師のみで分類機を作る方法の考察 あとインターンとか今後の人生
何がしたいか
現在私はESSLというweb技術を用いたワード一つから簡単に分類機を作成できる半教師あり学習の手法を提案し、開発に従事しています。
2値分類とは
私はそれを「一つの物体」「それ以外全て」だと認識しています。
「それ以外全て」を自動生成するのが非常に困難で、あらゆるアルゴリズムを模索中です。幸いCNNはNNが画像のどこを注視しているか取り出すことができるので(近年だとGrad-CAMという手法が盛んです)それを用いて取り組んだりはたまた人間では識別不能なランダムな画像生成を行なっています。
半教師あり学習および深層学習のハードルを下げ浸透することを願って開発を試みています。
最後に
私は大学院生ですが、正直本来の実験よりも開発が好きです。
OSSとか大好き人間で、人の役に立った時が何より嬉しいです。
前述のESSLもきちんとアーキテクチャを整備しOSSとして公開しています(まだ開発段階ですが)
そのため修士号を取得後、民間企業に就職をすると決めています。
webと深層学習、画像処理の技術があるのが強みだと思っています。
インターンなどを通して、就職活動を頑張りたい。
おわり
機械学習アプリケーションのレビューを受ける方法
ML特に深層学習についてはまだ世界的に確立されたコンテンツは少なく、あらゆる手法が試される中、kaggleなどを見ると年々新たな知見が生まれていることがわかります。
そんな深層学習界隈は、確立されたアルゴリズムの世界の様に正しいかそうでないかの判断が難しく、(数字が出てすらいても疑う余地はある)第三者からレビューを受けることは少し難しいです。
批評を得る方法を列挙します。
下に行くほど酷いです。
素人が有識者からレビューを得る方法
- 身近にいる人に聞く
これは情報系の大学に属している、もしくはML部門のある企業に属していないと難しいです。
しかしながら直接コミュニケーションを取れることもあり、もっとも新発見に近づくと考えています。
- 外部勉強会などで、勇気を持ってプレゼンする
勉強会はモチベーションの塊です。その空間の面積に対する知識力やポテンシャルの比エネルギーは凄まじいでしょう。
外部勉強会などは周りの方がとても優秀に見えて萎縮してしまい、交流や議論を躊躇ってしまいがちです。
しかし私の経験上それは一部の猛者を除いてほぼ全員が感じていることです。
一人が勇気を持って意見を出すことで、周りの方も連鎖的に意見をくれます。これは美味いです。
内容レベルがどれだけ低くても後からいくらでも勉強できるのでOKだと考えています。
実際聞いていて技術的にレベルが低いと感じるものも笑ったり貶したりする気持ちにはなりません。
要するに、「レベルが低い発表をする」という自身に来る羞恥に対するプライドがあるかないかです。
私はあんまりないので優秀なエンジニアの集まりの中でも初歩的な質問などを繰り返していました。
これは私の性格で、当然プライドがあることも素晴らしいと考えています。モチベーションの源泉となり、質の良いソフトウェアなどを生み出した知人を何人も知っています。私にはできないことです。
話が逸れましたがとにかく公の場で公開してみるといいです。
リポジトリとしてプログラムを残してあると、共感してくださった方がforkして強化してくれたりメールをくれたりします。
- 騒ぎまくる
普通に宣伝するといった範疇を超え、自演、複数アカウントなどインターネットでできる限りのことを駆使し自身のプロダクトを広めてもらいます。
これを自動化しようとするとスキルがついて美味しい。
それが炎上だろうがなんだろうが知ってもらえれば勝ちだと思います。
あるOS会社のプロダクトの初心者向け勉強会では、一人のアホ登壇者がその会社のエバンジェリストの女性を頂点とし、その場に居るであろう通常ユーザーを「一般ピープル」と位置付けヒエラルキーを持ったピラミッドを構築しました。
これはユーザーは不快に感じて当然でしょう。このあとMS社の人はケーキがどうとか登壇者のスライドをあらかじめ確認してなかっただか言ってましたが、無事叩かれていました。
しかしこれによりXamarinは広まったはずです。
こんな感じで自ら騒ぎを起こしましょう。
ネット上だけならマッチポンプである必要はなく、マッチだけで良いです。燃えれば燃えるほど美味しいです。
- OpenAIにメールを送る
OpenAIはメンバー募集の際、履歴書と共にgithubやMLアプリケーションの概要を要求します。
これにダメ元で応募すると、なんと細かなレビューがもらえるのです。
落ちても構いません。普通は落ちます。バシバシ送りましょう。