GENZITSU / UsefulMaterials

34 stars 0 forks source link

weekly useful materials -07/27- #62

Open GENZITSU opened 3 years ago

GENZITSU commented 3 years ago

Googleが20億パラメータのAIビジョンモデルをトレーニング

またImageNetのSoTaが更新された。

Google Brainの研究者は、20億個のパラメータを含むCVモデルを発表した。このモデルは30億枚の画像でトレーニングされ、ImageNetで90.45%のトップの精度を達成し、新たに最先端の記録を打ち立てた。

チーム、arXivで公開された論文でモデルと実験について説明した。ViT-G/14と呼ばれるこのモデルは、Googleの最近のVision Transformers(ViT)に関する取り組みをベースとしている。ViT-G/14は、ImageNet、ImageNet-v2、VTAB-1kなど、いくつかのベンチマークで以前の最先端のソリューションを上回った。数ショットの画像認識タスクでは、精度の向上は5パーセントポイント以上であった。

新しいViT-G/14モデルは、データセットの更新されたバージョンであるJFT-3Bで事前トレーニングされている。JFT-3Bは30億近くの画像を含んでいる。研究チームは、ViTアーキテクチャをいくつか改善した。メモリ使用率を改善して、モデルを単一のTPUv3コアに適合させることができた。

NLPの法則と同様のスケーリングの法則を定めた。

  • 計算、モデル、データをスケールアップさせると、べき乗則関数に従って、精度が向上する
  • 小さいモデルでは精度がボトルネックになる可能性がある
  • 大規模なモデルは、大規模なデータセットよるメリットがある

このモデルに関しては学習済みモデルの公開はないと、開発者が公言している。

コメント

進歩が早いなぁ。
そろそろImagenetでのベンチマークも意味を失いつつあると思うが...

出典

元記事

GENZITSU commented 3 years ago

朝飯前に学べる!便利なPythonのヒント100選【前編】

長いのでためになったところだけ抜粋。

1. forループのelse条件

# from https://qiita.com/baby-degu/items/05cf809d4d992923020d
numbers = [2, 4, 6, 8, 1]
for number in numbers:
    if number % 2 == 1:
        print(number)
        break
else:
    print("No odd numbers")

奇数が見つかった場合、breakを実行しelseブランチをスキップするため、その数字を出力します。それ以外はbreakを実行しないため、実行フローはelseブランチを実行します。

3. heapqモジュールを使用して、リストの最大値または最小値からn個の要素を取得する

# from https://qiita.com/baby-degu/items/05cf809d4d992923020d

import heapq

scores = [51, 33, 64, 87, 91, 75, 15, 49, 33, 82]
print(heapq.nlargest(3, scores)) # [91, 87, 82]
print(heapq.nsmallest(5, scores)) # [15, 33, 33, 49, 51]

8. Enumを使用して、同じ概念の関連項目を列挙する

Enumは、一意の値にバインドされた識別名の集合です。グローバル変数と似ていますが、より便利なrepr()やグループ化、型安全性などの機能があります。

# from https://qiita.com/baby-degu/items/05cf809d4d992923020d

from enum import Enum

class Status(Enum):
    NO_STATUS = -1
    NOT_STARTED = 0
    IN_PROGRESS = 1
    COMPLETED = 2
print(Status.IN_PROGRESS.name) # IN_PROGRESS
print(Status.COMPLETED.value) # 2

10. 数学のように3つの数字を比較する

# from https://qiita.com/baby-degu/items/05cf809d4d992923020d

x = 3
print (1 < x < 10) # True

12. タプルの要素のインデックスを取得する

# from https://qiita.com/baby-degu/items/05cf809d4d992923020d

books = ('Atomic habits', 'Ego is the enemy', 'Outliers', 'Mastery')
print(books.index('Mastery')) # 3

13. 文字列を文字列のリストに変換する

# from https://qiita.com/baby-degu/items/05cf809d4d992923020d

import ast
def string_to_list(string):
    return ast.literal_eval(string)

string = "[[1, 2, 3],[4, 5, 6]]"
my_list = string_to_list(string)
print(my_list) # [[1, 2, 3], [4, 5, 6]]

17. カスタム区切りを挿入した複数の値を出力する

# from https://qiita.com/baby-degu/items/05cf809d4d992923020d

print("29", "01", "2022", sep="/") # 29/01/2022
print("name", "domain.com", sep="@") # name@domain.com

22. アンダースコアを使用して、大きな数字を区切る

# from https://qiita.com/baby-degu/items/05cf809d4d992923020d

print(1_000_000_000) # 1000000000
print(1_234_567) # 1234567

29. 2つの辞書を簡単にマージする

# from https://qiita.com/baby-degu/items/05cf809d4d992923020d

dictionary_one = {"a": 1, "b": 2}
dictionary_two = {"c": 3, "d": 4}
merged = {**dictionary_one, **dictionary_two}
print(merged) # {'a': 1, 'b': 2, 'c': 3, 'd': 4}

コメント

一押しは

出典

元記事

GENZITSU commented 3 years ago

AIモデルの長年の課題「過学習」に見いだした世界初の知見とは?

さまざまな量子アルゴリズムで採用されている汎用的な量子回路について、量子ビットの数と量子回路の深さなどがモデルの表現力と過学習にどう影響するかを研究した。その結果、「量子回路の深さを増してパラメーターを増加させると、ある地点でモデルの表現力が飽和する」ことを数値実験で見いだした。

表現力の飽和は回路パラメーターを増加させても、それ以上モデルが複雑化せず、過学習が起きないことを意味する」(グリッド)。さらに理論保証として、モデルの複雑性の指標である「VC次元(学習モデルが完全に分類できる最大のデータ数を数値化したもの)」が上限値を持つことを証明した。

コメント

量子NNは過学習しづらいっぽいが、逆に言えばモデルの表現力に上限があるということよね...?
行末が心配だ...

出典

元記事

GENZITSU commented 3 years ago

InsightFace: 2D and 3D Face Analysis Project

顔認識ライブラリで結構新しめのモデルもカバーされている。

スクリーンショット 2021-07-28 22 20 14 スクリーンショット 2021-07-28 22 20 52 スクリーンショット 2021-07-28 22 21 10

使い方に関してはこちらのzennの投稿がわかりやすい

# from https://zenn.dev/yuyakato/articles/6a1d8177901381

face_analysis = insightface.app.FaceAnalysis()
face_analysis.prepare(ctx_id=0, det_size=(640, 640))

@app.post("/detect")
async def post_detect(file: fastapi.UploadFile = fastapi.File(...)):
    assert file.content_type == "image/jpeg"
    image = PIL.Image.open(file.file).convert("RGB")
    image = np.array(image)
    image = image[:, :, [2, 1, 0]]  # RGB to BGR

    faces = face_analysis.get(image)

    file.file.seek(0)
    sha1_hash = hashlib.sha1(file.file.read()).hexdigest()
    file_size = file.file.tell()

    return {
        "service": SERVICE,
        "time": int(datetime.datetime.now().timestamp() * 1000),
        "request": {
            "file": {"name": file.filename, "size": file_size, "sha1": sha1_hash}
        },
        "response": {
            "width": image.shape[1],
            "height": image.shape[0],
            "numberOfFaces": len(faces),
            "faces": [
                {
                    "score": face.det_score.astype(float),
                    "boundingBox": {
                        "x1": face.bbox[0].astype(float),
                        "y1": face.bbox[1].astype(float),
                        "x2": face.bbox[2].astype(float),
                        "y2": face.bbox[3].astype(float),
                    },
                    "keyPoints": [
                        {"x": xy[0].astype(float), "y": xy[1].astype(float)}
                        for xy in face.kps
                    ],
                    "landmarks": {
                        "2d_106": [
                            {"x": xy[0].astype(float), "y": xy[1].astype(float)}
                            for xy in face.landmark_2d_106
                        ],
                    },
                    "attributes": {"sex": face.sex, "age": face.age},
                    # TODO: face.embedding
                }
                for face in faces
            ],
        },
    }

コメント

検出結果で用意されているattributesがめちゃくちゃ優秀。

出典

元記事

GENZITSU commented 3 years ago

魚眼レンズで角度のある人物を検出する機械学習モデル「RAPiD」を動画対応してみた。

RAPiDは「Rotation-Aware People Detection in overhead fisheye images」の略 つまり「角度を意識した」人物検出、ということ

YOLOをベースにCOCOデータセットで学習をおこなった後に魚眼レンズにて追加学習を行い、その際に画像の中心とそこからの距離、角度の情報を加えています。 そうすることで自動的にその人物をバウンディングボックスで囲った時の角度まで推論できる その角度を推論するのも含めた損失関数を拡張(周期的損失関数)しているため、推論は一回で済み、YOLOと推論する速さはほぼ変わらない

スクリーンショット 2021-07-28 22 27 39

コメント

魚眼レンズに対応したモデルがあることは知らなかった。
コードの商用利用が不可なのがつらみ

出典

元記事

元コード (商用利用不可)

GENZITSU commented 3 years ago

AWSを活用した機械学習モデルの継続的な運用改善

アーキテクチャー図

スクリーンショット 2021-08-03 20 44 08

AWSでの構成図

スクリーンショット 2021-08-03 20 44 36

機械学習モデルの学習ジョブ・モデル管理・バッチでの推論処理はAmazon SageMakerを用いて実装できます。 一方で、今回の様なバッチでの推論精度監視には、SageMaker Model Monitorを利用できないため、別途開発が必要 さらに、機械学習モデルの再学習についても、Amazon SageMakerの学習ジョブを起動する機能の開発が必要

今回は、バッチでの推論精度監視を、AWS Lambda、Amazon CloudWatch、Amazon SNSを利用して開発しました。また、精度劣化検知時の再学習機能を、AWS Step FunctionsとAWS Lambdaを利用して開発

コメント

Amazon SNSを通す必要はあるのだろうか? なんとかんCloudWatchからそのままLambdaを起動できそうだけども

3分で作る、CloudWatchイベントで実行するLambda

出典

元記事

GENZITSU commented 3 years ago

限られたデータからの深層学習

学習データが少ない状況下での方法論を整理しつつ、自己教師あり学習やFomura-driben Approachなどを手厚く紹介している。 全117pの大作。

スクリーンショット 2021-07-28 23 37 45 スクリーンショット 2021-07-28 23 38 01 スクリーンショット 2021-07-28 23 39 35 スクリーンショット 2021-07-28 23 40 15 スクリーンショット 2021-07-28 23 40 42

自己教師あり学習はさまざまな手法の概要も簡単にまとめられているのでとても良い。

コメント

とてもありがたいチュートリアル資料。

出典

元記事

GENZITSU commented 3 years ago

テキストデータのかさましを実装する

一休.comのデータサイエンティストが書いたEDA: Easy Data Augmentation Techniques for Boosting Performance on Text Classification Tasksを日本語データに使ってみたブログ。

スクリーンショット 2021-07-29 11 34 45

同義語に置き換える方法をWordNetからとChive(Word2vec)からの2通り試しています。

EDAの実装

# from https://user-first.ikyu.co.jp/entry/2021/07/27/155513

alpha = 0.3 # 単語を操作する割合
N_AUG = 16 # 一文から増やす文章の数(倍率)、500: 16, 2000: 8, 5000: 4
def synonym_select(target_token):
    if target_token.part_of_speech()[0] == '動詞' or \
        (target_token.part_of_speech()[0] == '形容詞' and target_token.part_of_speech()[1] == '一般'):
        target_word = target_token.dictionary_form()
    else:
        target_word = target_token.surface()

    synonyms = search_similar_words(target_word)

    if len(synonyms) > 0:
        replacement = random.choice(synonyms)
    else:
        # 同義語が無かったら置換しない
        replacement = target_token.surface()

    return replacement

# Synonym Replacement 文中の単語の内n個、同義語に置き換える
def synonym_replacement(text_tokens, text_split, text_length):
    n = math.floor(alpha * text_length)
    indexes = [i for i in range(text_length) if text_tokens[i].part_of_speech()[0] in ['名詞', '動詞', '形容詞']]
    target_indexes = random.sample(indexes, min(n, len(indexes)))

    for i in target_indexes:
        target_token = text_tokens[i]
        replacement = synonym_select(target_token)
        text_split[i] = replacement

    return text_split

# Random Insertion 文中の単語をランダムに選んで同義語にしてランダムな場所にinsert、n回繰り返す
def random_insertion(text_tokens, text_split, text_length):
    n = math.floor(alpha * text_length)
    indexes = [i for i in range(text_length) if text_tokens[i].part_of_speech()[0] in ['名詞', '動詞', '形容詞']]
    target_indexes = random.sample(indexes, min(n, len(indexes)))

    for i in target_indexes:
        target_token = text_tokens[i]
        replacement = synonym_select(target_token)
        random_index = random.choice(range(text_length))
        text_split.insert(random_index, replacement)

    return text_split

# Random Swap 文中の二つを入れ替える n回繰り返す
def random_swap(text_split, text_length):
    if text_length < 2:
        return ''.join(text_split)

    n = math.floor(alpha * text_length)
    target_indexes = random.sample(range(text_length), 2)

    for i in range(n):
        swap = text_split[target_indexes[0]]
        text_split[target_indexes[0]] = text_split[target_indexes[1]]
        text_split[target_indexes[1]] = swap

    return text_split

# Random Deletion 確率pでランダムにそれぞれの単語削除
p = alpha
def random_deletion(text_split, text_length):
    return [t for t in text_split if random.random() > p]

# Easy Data Augumentation 
def eda(text_tokens, text_split, text_length):
    results = []
    for _ in range(N_AUG):
        text_tokens_c = copy.copy(text_tokens)
        text_split_c = copy.copy(text_split)

        random_number = random.random()
        if random_number < 1/4:
            result_arr = synonym_replacement(text_tokens_c, text_split_c, text_length)
        elif random_number < 2/4:
            result_arr = random_insertion(text_tokens_c, text_split_c, text_length)
        elif random_number < 3/4:
            result_arr = random_swap(text_split_c, text_length)
        else:
            result_arr = random_deletion(text_split_c, text_length)

        results.append(''.join(result_arr))
    return list(set(results))

WordNet ベースの置換

# from https://user-first.ikyu.co.jp/entry/2021/07/27/155513

conn_sqlite = sqlite3.connect("wnjpn.db")
re_alnum = re.compile(r'^[a-zA-Z0-9_]+$')

# 特定の単語を入力とした時に、類義語を検索する関数
def search_similar_words(word):
    # 問い合わせしたい単語がWordnetに存在するか確認する
    cur = conn_sqlite.execute("select wordid from word where lemma='%s'" % word)
    word_id = 99999999  #temp 
    for row in cur:
        word_id = row[0]

    # Wordnetに存在する語であるかの判定
    if word_id==99999999:
        return []

    # 入力された単語を含む概念を検索する
    cur = conn_sqlite.execute("select synset from sense where wordid='%s'" % word_id)
    synsets = []
    for row in cur:
        synsets.append(row[0])

    words = []
    for synset in synsets:
        cur3 = conn_sqlite.execute("select wordid from sense where (synset='%s' and wordid!=%s)" % (synset,word_id))
        for row3 in cur3:
            cur3_1 = conn_sqlite.execute("select lemma from word where wordid=%s" % row3[0])
            for row3_1 in cur3_1:
                words.append(row3_1[0])

    return list(set([w for w in words if not re.search(re_alnum, w)]))

Word2Vecベースの置換

vectors = gensim.models.KeyedVectors.load("chive-1.1-mc90-aunit.kv")
def search_similar_words(word):
    thre = 0.6
    try:
        result = vectors.most_similar(word, topn=20)
        return [r[0] for r in result if r[1] > thre]
    except:
        return []

生成例の比較 WordNet

お肉がとても美味しかったです。食後のコーヒーが別料金(210円)なので、そこだけ注意です。
=>
おミートがとても美味しかったです。食後のカフェーが画然たる勘定(210円型)なので、そこだけ注目です。

Word2Vec

お肉がとても美味しかったです。食後のコーヒーが別料金(210円)なので、そこだけ注意です。
=>
1. お胸肉がとても美味しかったです。空腹の水出しが各料(210¥)なので、そこだけ呉々です。
2. お肉がとても美味しかったコーヒーショップです。
¥食後のコーヒーが別料金(210円)な違う間食のでジューシー金額、細心ソーセージそこだけ注意です。

ブログでは、レストランの口コミから評価点(1~5)を予測するタスクをLSTMで実施。 DAをすればするほど、性能が上がる模様。

スクリーンショット 2021-07-29 11 46 09 スクリーンショット 2021-07-29 11 46 15 スクリーンショット 2021-07-29 11 46 27

コメント

割と効果ありそうなので、使いたい。
類似語検索の部分は、BERTによる置き換えとかも追加しても良さそう。

出典

元記事

GENZITSU commented 3 years ago

Q. AI企業の決算からわかる、3つの成長ドライバーとは?

以下の企業の決算から、AI企業の成長を促す3要素を紐解いている。

A.3つの成長ドライバー

・クロスセルや大口顧客増加による、1顧客あたり単価向上(WACUL、AI inside)

・顧客基盤の拡大(PKSHA Technology、ニューラルポケット)

・対象顧客の拡大(PKSHA Technology、ALBERT)

PAKSHA, ALBERTの今後の戦略が面白い。

スクリーンショット 2021-07-29 20 44 05 スクリーンショット 2021-07-29 20 44 34

コメント

PAKSHAの図はとても参考になる。

出典

元記事

GENZITSU commented 3 years ago

データセットの描画簡単にできるライブラリ: ipyplot

matplotlibをガチャガチャ描かなくても、データセットのグリッド表示が可能になる。

example1-tabs

チュートリアルはこちら

大まかな使い方

# from https://github.com/karolzak/ipyplot/blob/master/notebooks/gear-images-examples.ipynb

images = glob.glob(datasets_dir + 'gear_images' + '/**/*.*')
images = [image.replace('\\', '/') for image in images]
labels = [image.split('/')[-2] for image in images]

ipyplot.plot_images(images, max_images=10, img_width=150)

コメント

めっちゃ便利そう

出典

元github

GENZITSU commented 3 years ago

MediaPipeで姿勢推定を行い、Tokyo2020オリンピック風のピクトグラムを表示するデモ

https://user-images.githubusercontent.com/37477845/127340964-5378706f-034a-4920-be23-c6fbca442686.mp4

コメント

MediaPipeを扱う良いサンプルな気がする。

出典

元github

GENZITSU commented 3 years ago

文書分類における古典的手法とBERTの判断根拠の比較

UCIのSMS Spam Collection Data Setを用いて、以下の手法を試したブログ

LIMEが一番直感に近かった模様。

ロジスティック回帰

CountVectorizer+回帰係数で可視化

スクリーンショット 2021-07-29 22 08 08

BERT

最終CLSトークンのattentionの合計をとっている。
全体的に高く出てしまう模様。また、非スパム/スパム共通の色となる。

スクリーンショット 2021-07-29 22 07 25

LIME

サンプリングしたテキスト列と予測をLIMEに渡して実装。   結構よい

スクリーンショット 2021-07-29 22 04 19 スクリーンショット 2021-07-29 22 04 08

Grad-CAM

全体的に高く出てしまう。

スクリーンショット 2021-07-29 22 03 50

コメント

実装も参考になるとても良い記事。

出典

元記事

GENZITSU commented 3 years ago

事業やプロダクト開発を加速させるデータ分析

事業のフェーズとしてはPMFして、拡大させていこうとするフェーズです。PMFしているからといって、プロダクトが完璧ということは全然なく、データ分析を駆使してプロダクトを改善しています。 その際に、特に次の2点が大切と感じており、順を追って説明します。 ・現場とデータの両面からの分析 ・データ分析がしやすい環境作り

データがあるとデータとにらめっこして示唆を出そうとしますが、現場に行って、定性情報を得ることでそもそもデータに現れないような課題を発見するのが重要です。 現場や営業からの声に触れることで、課題の解像度が上がり、データをどの切り口で分析すれば良いかが分かります。

一方で、データ→現場のパターンもあります。データから外れ値や解釈が難しい要素を抜き出します。そのデータが起きる原因を現場に行って確認すると、我々が想定していなかったプロダクトの使われ方をしていて、プロダクト改善につながったケースもあります。

この段階の事業フェーズでは、因果推論や多変量解析などの高度な手法は使わず、クロス集計のような単純な方法で明らかに課題がある箇所を特定することが多いです。 ただ、差分の差分法(DID)や回帰不連続デザイン(RDD)などの概念を知っていると、分析の切り口が増えて役立ちます。例えば、特定のセグメントで施策をしたときに、施策前にそれぞれのセグメントで平行なトレンドがあるのかを確認した上で、試作後の影響度合いを確認することを徹底しています。

データ分析をする際には、そこからどんなアクションに繋がるかを念頭に置くことも大切です。 実際にプロダクト改善に繋がる示唆というのは、そこまで多くありません。 プロダクトを改善するとその数値が変わりうるのか、プロダクトの変更コストはどれくらいで、それを変えたときのインパクトはどれくらいかを考えながら分析することが大事で、現場感とプロダクトに対する深い理解が求められます。

コメント

現場とデータ両方に気を配る必要がある。
ドメイン知識とはまさしくこのことかも。

出典

元記事

GENZITSU commented 3 years ago

ソフトウェア開発における人的リソースの理想的な配分

ソフトウェア開発の代表的なタスク

スクリーンショット 2021-07-30 0 56 58
  • 機能開発: 事業上の直接的価値貢献になる開発
  • 不具合修正: 既存機能における仕様とのズレを直す開発
  • Overhead: 機能開発以外のMTGや、採用や評価といった事務作業などのシステムの価値向上につながらない営み
  • Ops Engineering: 信頼性向上のための自動化やインフラの設定。一度行うと価値が蓄積する点が Toil とは異なる
  • Toil: 繰り返され、自動化できるのに手動で行っており、対処療法的に発生し、長期的な価値がない作業。事業成長に比例した工数がかかる

Toil は放置しておくとどんどん増え続けるため、Ops Engineering の活動によってそれを抑制し続ける必要がある Overhead は組織の都合で決まるものなので、割合を抑えることができる。

理想的な時間配分

スクリーンショット 2021-07-30 1 00 32

タスク間には以下の関係性がある

スクリーンショット 2021-07-30 1 05 13

特に重要なのは

組織成長すると Overhead が増える Overhead には要件品質を向上したり技術力そのものを向上するトレーニングが含まれるので、部分的に開発品質向上に貢献する 機能開発は事業成長に貢献するが、開発品質という係数がかかる 開発品質が落ちると不具合修正工数が増える Ops Engineering によって Toil を抑えることができる

以下のようなケースが考えられる。

1. 不具合修正が多い

これは開発品質が低いことを意味するので、「要件を正確にするるためのMTGを増やす」「アーキテクチャーやテスト技法を習得するためのトレーニングを増やす」「Ops Engineering を増やす」ことで開発品質を向上させる必要がある

2. Toil が多い

これは、急激な事業成長によって Ops Enginnering が不足していることが原因である。 Toil は事業成長によって減ることはないが、早めに Ops Engineering に割り当てることで撲滅していく必要がある

3. Overhead が多い

組織が大きくなるとナレッジを共有するためにどうしても同期的なコミュニケーションが必要になり、気づいたら「週の半分 MTG だった」ということになりかねない。 スクラムの定常イベント(朝会やリファインメントなど)は思った以上に全体の工数を圧迫する

一方、望ましい Overhead も存在する。それが「要件の精緻化」と「トレーニング」である。

要件があいまいなまま開発に着手し、あとから大きな手戻りが発生したことがある人は多い。

アーキテクチャの審美眼やテスト方法、 CI/CD の構築方法などは時間を割いてチームのナレッジとする価値がある。ここを疎かにすると近い将来属人化が進み、開発品質が上がらなくなる

それでもダメな場合。

織やシステムが必要とする人的リソースに対して、実際の頭数・スキルレベルが不足している。 短期的には業務委託でカバーし、中長期的には採用を行おう。

コメント

平社員だけどとてもためになる。

出典

元記事

GENZITSU commented 3 years ago

指先の向きや手の重なりまで認識できる3D姿勢推定技術を開発

シミュレーションデータ x AIが来ている。。

今回、3DCGによる人体シミュレーションによって大量の学習データを作成し、それをPFNのスーパーコンピュータで学習して、全身を総合的に認識できる高度な3D姿勢推定モデルを構築。専用カメラによる撮影や、身体へのセンサー装着の必要がなく、これまでの技術で課題となっていた指先の向きや両手が重なる場面などでの誤検出を大幅に削減し、 スマートフォン等で撮影した動画でも身体細部の動きを高精度にトラッキングできるようになりました。

コメント

モデリングスキル結構大事になりそう。

出典

[元記事]()

GENZITSU commented 3 years ago

カメラ1台で100羽以上を行動データ収集。「養鶏AI」の生かし方

山形大学の片平光彦教授と堀口健一教授、ViAR&Eの市浦茂社長は深層学習を使った鶏の行動判定技術の開発に注力する。 4000枚の画像を学習させることで採餌と水飲み、休憩の識別率が100%になった

食肉用のブロイラーは平飼いが主流。平飼いなら天井に設置したカメラ1台で鶏100羽以上の行動データを集められる。

同時に羽紋で1羽ごとに個体識別して追跡する技術も開発中。 1羽ごとに体重が増える速度を記録して活動量を可視化する。 鶏は別の鶏をつつき羽根をむしるなど厳しい序列をつくる習性がある。そのため、集団の中でいじめられ弱っている固体を特定できれば、区画を入れ替えるなど対応ができる

鹿児島大学の小沢真准教授は、富士通鹿児島インフォネットや中嶋製作所などと共同でカメラ映像から鶏の体重や活動量を推定する技術を開発した。 画像認識AIで鶏を識別し、画像の鶏の大きさから立体的な体積を求め、体重を算出する。推定誤差は調整前でプラスマイナス5%

活動量の計測では鶏を識別して数秒後の画像でどれだけ移動したかを計算する。鶏が風邪をひいて活動量が下がるなど病気で死ぬ予兆を探す。日々の変化に対し、急に活動量が減ると何か異常が起きているというサインにもなる。

コメント

意外と平飼いの鶏に対するプロダクとが多くて驚いた。

鳥の識別ってどうやってるんだろう...?羽紋ってのがあるみたいなので、それを使えば指紋みたくできる感じ..?

出典

元記事

GENZITSU commented 3 years ago

pytorchでtesnroRTを用いた場合の速度表

公式レポジトリの表が意外と使える。

スクリーンショット 2021-07-30 19 35 21

コメント

物によっては10倍程度早くなるものもあるのが驚き。 ただし、物体検出系は早くなりづらいんだとか。

出典

元記事

GENZITSU commented 3 years ago

__slots__を用いることで、クラスのメモリ使用率を削減できる。

slots を使うと、(プロパティのように) データメンバを明示的に宣言し、 (明示的に slots で宣言しているか親クラスに存在しているかでない限り) dictweakref を作成しないようにできます。 dict を使うのに比べて、節約できるメモリ空間はかなり大きいです。 属性探索のスピードもかなり向上できます。

slotsにはいくつか注意点があるようだ。

  • slots を持たないクラスから継承するとき、インスタンスの dict 属性と weakref 属性は常に利用可能
  • dict 変数がない場合、 slots に列挙されていない新たな変数をインスタンスに代入することはできません。新たな変数を動的に代入したいのなら、 slots を宣言する際に 'dict' を変数名のシーケンスに追加してください。
  • slots は、クラスのレベルで各変数に対するデスクリプタ (デスクリプタ (descriptor) の実装 を参照) を使って実装されます。その結果、 slots に定義されているインスタンス変数のデフォルト値はクラス属性を使って設定できなくなっています; そうしないと、デスクリプタによる代入をクラス属性が上書きしてしまうからです。
  • あるクラスで、基底クラスですでに定義されているスロットを定義した場合、基底クラスのスロットで定義されているインスタンス変数は (デスクリプタを基底クラスから直接取得しない限り) アクセスできなくなります。これにより、プログラムの趣意が不定になってしまいます。将来は、この問題を避けるために何らかのチェックが追加されるかもしれません

実際どれくらいのメモリ節約ができるのだろうか。

class Point(object):
    def __init__(self):
        self.x = 0
        self.y = 0

print(sys.getsizeof(Point))
>>> 1056

point = Point()
print(sys.getsizeof(point))
> 56
class Point(object):
    __slots__ = ['x', 'y']
    def __init__(self):
        self.x = 0
        self.y = 0

print(sys.getsizeof(Point))
>>> 888

point = Point()
print(sys.getsizeof(point))
> 56

どうもインスタンスのメモリは減らないが、classの方のメモリ使用量が減る模様。

コメント

減るっちゃ減るけど、ここまでメモリを減らさなくては行けない場面ってそこまでないのかも。

出典

元記事

GENZITSU commented 3 years ago

Googleがトークンフリー言語モデルByT5をオープンソース化

Google Researchは、ByT5をオープンソース化している。これは抽象的なトークンの代わりに未加工のバイトで動作するモデルである。ベースラインモデルと比較して、ByT5はいくつかのベンチマークタスクでより正確であり、スペルミスやノイズに対してより堅牢である。

バイトレベルの処理では、ベースラインと比較して推論時間が遅くなりますが、ByT5はmT5よりもノイズに対してはるかに堅牢である。経験として、ランダムに大文字や小文字を変更したテキストが与えられた場合、mT5の25%と比較して1%の精度低下で済んでいる。ByT5は、生成タスクおよびXTREME多言語NLPベンチマークでもmT5よりも優れている。

バイトレベルモデルの欠点の1つは、モデルの後続のレイヤーに供給される結果のシーケンスがトークン化されたものよりもはるかに長く、その結果、モデルが大きくなり、遅くなることである。

ByT5を実装するために、研究者は3つの方法でmT5アーキテクチャを変更した。

  • UTF-8バイトがモデルに直接提供される。ただし、UTF-8で無効なバイトはすべて削除され、パディングと文の終わりを表すために2つの特別なトークンが使われる。
  • トレーニング前のスパン破損タスクが変更され、平均3トークンをマスクするmT5と比較して、平均20バイトがマスクされる。
  • 最後に、エンコーダーとデコーダーに同じ数のTransformerブロックを使うのではなく、ByT5ではエンコーダーの深さはデコーダーの3倍となる。

byT5はSuperGLUE(言語理解)やXSumとTweetQA(生成タスク)、XTREMEなどのタスクでmT5よりも性能が高かったものの、その他のタスクではまちまちだった。

ByT5は低速で、事前トレーニングを完了するのに33%長いクロック時間がかかり、推論時間は分類で最大2倍、生成で最大7倍遅かった。

コメント

CHNINEとの根本的な違いはなんだろうと思って調べてみたら、こう描かれていた。

though the “CANINE-S” model still uses a tokenizer during pre-training to define targets for the masked language modeling task. (a) we train encoder-decoder models that extend to generative tasks, (b) our models work directly with UTF-8 bytes (c) we explore the effect of model scale, training models beyond 10 billion parameters.

出典

元記事

github

GENZITSU commented 3 years ago

文字の図形的な埋め込み表現 GLYPH-AWARE CHARACTER EMBEDDING

文字を画像にした後にConvolutional AEで再構成させることで、文字の図形的な埋め込み表現を獲得する。

フォントが図形として描写可能なすべての文字に対して、背景が黒色で文字が白色の60x60の画像を作成しました。学習の際には、画像をグレースケールに変換後に正規化しました。

埋め込み表現の利用はgensimが使える。

from gensim.models import KeyedVectors

model = KeyedVectors.load_word2vec_format("data/convolutional_AE_300.bin", binary=True)
In []: model.most_similar("油")
Out[]:
[('汕', 0.9025427103042603),
 ('泊', 0.8892871737480164),
 ('伷', 0.884428083896637),
 ('浊', 0.8678311109542847),
 ('沖', 0.8532482385635376),
 ('沽', 0.8451510667800903),
 ('沺', 0.8355003595352173),
 ('沾', 0.8313066959381104),
 ('涃', 0.8284391164779663),
 ('泩', 0.8275920152664185)]

コメント

かなり面白い試み。
誤字に強くなりそう。

AEをVAEにするのも良いかもしれない。

出典

元記事

github

GENZITSU commented 3 years ago

Twitter、投稿画像自動切り抜きアルゴリズムに潜む「バイアス」発見者に最大3500ドルの報奨金コンテスト実施

Twitterが、システムが自動的に画像をクロップする際の”偏り”を発見した人に謝礼を支払う報奨金コンテストを開始しました。

Twiiterの自動画像クロップは2018年から使われ始めましたが、一部ユーザーからはこのアルゴリズムが肌の白い人を中心にするようなバイアスがかった処理を行う傾向があると批判の声が上がっていました。

この報奨金コンテストは「業界初」のアルゴリズムのバイアスを対象とした報奨金プログラム

コメント

機械学習のバイアスを探すコンペティションはかなり面白い試み。
社会的な問題として批判されるよりも、ユーザーに事前に発見してもらえるほうが企業的には利があるのだろう。
報奨金は最高3500ドルであるので、実際どの程度の人が参加するかが今後の資金石となるだろう。

出典

元記事

GENZITSU commented 3 years ago

天才ではない私たちがコードを書く上でやってはいけない過ち

気になったものを抜粋。

NG: 1日以上かかりそうなタスクの分解をしない → 時間がかかりそうなタスクは2、3時間で終わる単位に分割しよう

NG: 技術調査をするときに、メモを取らない → 調べる際に参考にしたサイトのURLをメモしておくと、時間を溶かすことなく調査が進むだろう

NG: 他人と比較する → そもそも近年のプログラミングはかなり多岐に渡るのでわからないことは無限にある。 比較をすること自体がナンセンスだ ある程度のレベルまでいくと比較はあまり意味をなさない。

NG: 複数の機能開発を同時に行う → コードを書く際は一定の時間を確保しましょう

コメント

肝に銘じていきたい。

出典

元記事

GENZITSU commented 3 years ago

【デブサミ2021】講演関連資料まとめ

開発資料 とTogetter がまとめられている。

気になったのは以下。

【18-C-1】「スピード」と「品質」のスイッチング ~事業成長を支える生存戦略~(城戸 総史[メルペイ]/長谷川 亮[メルペイ]/横山 翔)

別の資料まとめもああった。

https://qiita.com/e99h2121/items/8011b49df00ab7d4fa23?utm_campaign=popular_items&utm_medium=feed&utm_source=popular_items

フルサイクル開発を加速する組織的エッセンス

ビジネス考えてるかい?事業の持続的成長を促進させるシステム設計の考え方

素早く賢く失敗するDeveloper Productivityの実現を目指して

コメント

時間ある時にじっくり読みたい。

出典

[元記事]()

GENZITSU commented 3 years ago

PythonとHoraを使用して、非常に高速な顔認識システムを作成します

Horaという高速なベクトル検索ライブラリを用いた顔認識システムの構築例

スクリーンショット 2021-08-01 23 19 39

特徴は以下

スクリーンショット 2021-08-01 23 20 40

依存関係が少なく、さまざまなOSやモバイル端末で使用可能。 SIMD命令を利用しているため高速な模様。

コメント

ベクトル検索ライブラリいろいろ出てきてる。
こいつは速度のわりに、recallが高い。

出典

元記事

GENZITSU commented 3 years ago

現場で使用していたGitコマンド集

気になったものだけ抜粋

git checkout . ステージングされていない修正を取り消す。

コメント

よく用いられるコマンドが列挙されているので復習に良い。

出典

元記事

GENZITSU commented 3 years ago

Python multiprocessing vs threading vs asyncio

前提

マルチプロセスとは プロセスとは実行中のプログラムです。 1つのプロセスは、OSから空いているCPUコアが割り当てられることにより、処理を進めることができます。 マルチプロセスとは、複数のプロセスが同時に処理を進めることを指します。マルチプロセスのメリットは、1つのプログラムの目的を達成するために複数のCPUのコアを利用することで、より速く目的を達成できるという点

マルチスレッドとは スレッドとは、プロセスの中における処理の流れのことです。 1つのスレッドは、プログラミング言語毎に実装されている機構(LinuxではPthread、JavaのThreadsライブラリ、Pythonではやthreadingライブラリ等)を通してCPUコアが割り当てられることにより、処理を進める プロセスのように、OSから直接CPUコアが割り当てられるのではありません。 プロセスの場合と同様に、CPUのコアが複数ある場合、それぞれのコアを複数のスレッドに対して同時に割り当てることができれば、複数のスレッドの処理を同時に進めることができます。

ここでいうスレッドとは、

print('Hello')、print('world')、print('!')、そしてメインスレッドの4つの処理のことで、job.join()関数の実行後はスレッドが完了します。 print('done')が実行される時点においては、スレッドはメインスレッドの1つだけです。


# from https://tech.jxpress.net/entry/2021/07/29/101150

import threading

jobs = [] jobs.append(threading.Thread(target=lambda : print('Hello'))) jobs.append(threading.Thread(target=lambda : print('world'))) jobs.append(threading.Thread(target=lambda : print('!')))

for job in jobs: job.start() for job in jobs: job.join()

print('done')



> Pythonにおけるマルチスレッド
> Pythonにおいて、マルチスレッドなソースコードを書く場合、CPythonがGILがあることを考慮しなければなりません。
> GILであるインタプリターにおいては、マルチスレッドなソースコードを書いたとしても、インタプリターが出力したバイトコードをOS上で実行する段階においてマルチスレッドでは実行されません。

### 比較実験 ①
> CPU負荷の高い処理(いわゆるCPU bound)を達成するためのソースコードである場合、multiprocessingを利用し、マルチプロセスに書きましょう
> CPU負荷の高い処理するためにマルチスレッドなソースコードを書いたとしても、パフォーマンスは改善されません。なぜなら、「Pythonにおけるマルチスレッド」で説明した通り、Pythonのソースコードはインタプリターによりコンパイルされた後、OS上でシングルスレッドで実行されるからです。

<img width="500" alt="スクリーンショット 2021-08-02 13 01 28" src="https://user-images.githubusercontent.com/19774756/127802750-8a468151-92c6-4f34-a41d-707e3c9d7050.png">

### 比較実験②
> I/O待ち時間が大きいもの(いわゆるI/O bound)を達成するためのソースコードである場合、threading(マルチスレッド)かasyncio(非同期I/O)を利用しましょう。

> multiprocessing(マルチプロセス)を利用しない方が良い理由は、プロセスを作る際に発生するコストが大きいから
> プロセスを作るコストよりもスレッドを作るコストの方が小さいので、コストが小さい方を利用した方が良い
> プロセスを新しく作ると、新しく作られたプロセスの数に比例してファイルディスクリプタ数、OSがCPUを切り替えるためのスイッチング回数が大きくなります

> スレッドを作るコストという観点から言えば、スレッドを作るコストよりも非同期I/Oのイベントを発火するコストの方が小さいため、asyncioを利用する方が良い

<img width="400" alt="スクリーンショット 2021-08-02 13 07 16" src="https://user-images.githubusercontent.com/19774756/127803096-4b61ba52-88ed-4b9f-ab0a-87a27b0203bd.png"><img width="400" alt="スクリーンショット 2021-08-02 13 07 42" src="https://user-images.githubusercontent.com/19774756/127803134-690f9b78-9864-4c96-82c3-92d877fd0e63.png">

ここからわかることは
> (1)過度なタスク分割によるオーバーヘッド増大
> スレッドやイベントループ、その他諸々のオーバーヘッドの影響が大きくなってしまったことが起因していると考えられます。
> タスクを小さくすればするほどそれぞれのスレッドは速く終了しますが、よりたくさんのスレッドを生成・管理しなければなりません

> (2)OSのスレッド数上限値が影響
>  1プロセス毎に作ることのできるスレッド数には上限値があります。CPythonのスレッドはpthreadを用いて実装されているため、この上限値の影響を受けます。

> (3)パフォーマンス頭打ち
> 理想的なパフォーマンスの向上が頭打ちになっている状態です。

> (4)タスク分割数に比例してパフォーマンス向上
>  単タスクの量と処理時間がほぼ同じです。マルチスレッド、非同期I/O、共に、理想的なパフォーマンスの向上が実現できています。
> io_threading.pyとio_asyncio.pyの処理時間に差異がほとんどありません。これは(1)で述べたようなオーバーヘッドの影響が無視できるほど小さいからだと思われます。

### コメント
pythonでの並列処理はややこしく、いまいち理解ができていなかったので、とても勉強になった。

### 出典
[元記事](https://tech.jxpress.net/entry/2021/07/29/101150)
GENZITSU commented 3 years ago

Getting Started With Faiss

Faissのチュートリアルがjupyter notebook 形式でまとめられている。 スピードと精度の兼ね合いや、quantization、ベクトルの復元などの方法についての言及もある。

コメント

表題の通り。

出典

元記事

GENZITSU commented 3 years ago

自然言語で書かれた時間情報表現を抽出/規格化するルールベースの解析器

ja-timex は、現代日本語で書かれた自然文に含まれる時間情報表現を抽出しTIMEX3と呼ばれるアノテーション仕様に変換することで、プログラムが利用できるような形に規格化するルールベースの解析機です。

以下の機能を持っています。

  • ルールベースによる日本語テキストからの日付や時刻、期間や頻度といった時間情報表現を抽出
  • アラビア数字/漢数字、西暦/和暦などの多彩なフォーマットに対応
  • 時間表現のdatetime/timedelta形式への変換サポート

入出力例

# from https://github.com/yagays/ja-timex/

from ja_timex import TimexParser

timexes = TimexParser().parse("彼は2008年4月から週に3回ジョギングを1時間行ってきた")

[<TIMEX3 tid="t0" type="DATE" value="2008-04-XX" text="2008年4月">,
 <TIMEX3 tid="t1" type="SET" value="P1W" freq="3X" text="週に3回">,
 <TIMEX3 tid="t2" type="DURATION" value="PT1H" text="1時間">]

datetimeやtimedeltaなどにも変換可能らしい

コメント

めっちゃ便利そう

出典

github