2023,江端さんの忘備録

https://aravisproject.github.io/aravis/building.html
と、
cam@cam-desktop:~/download/aravis-0.8.10$README.md

の内容を参照にして、ざっくり以下の内容を実施しました。

(Step.1)
https://download.gnome.org/sources/aravis/ から、https://download.gnome.org/sources/aravis/0.8/ の LATEST-IS-0.8.10(最新であれば良い)から、aravis-0.8.10.tar.xz をダウンロードして、解凍。(私は、:~/download/にダウンロード)

(Step.2) cam@cam-desktop:~/download/aravis-0.8.10$ で、

$ meson setup build
$ cd build
$ ninja
$ ninja install
$ sudo ldconfig

$ sudo apt install libxml2-dev libglib2.0-dev cmake libusb-1.0-0-dev gobject-introspection \
libgtk-3-dev gtk-doc-tools xsltproc libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1.0-dev \
libgirepository1.0-dev gettext
 として、

cam@cam-desktop:~/download/aravis-0.8.10/build$ ninja test

実行すると
[0/1] Running all tests.
1/6 aravis:main / evaluator OK 0.07s
2/6 aravis:main / buffer OK 0.06s
3/6 aravis:main / misc OK 0.08s
4/6 aravis:main / genicam OK 0.20s
5/6 aravis:main / fake FAIL 1.60s killed by signal 6 SIGABRT
>>> MALLOC_PERTURB_=127 /home/cam/download/aravis-0.8.10/build/tests/fake
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― ✀ ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
stdout:
# random seed: R02S5b8ac58722df24f3d23b19ba049cf5e1
1..8
# Start of fake tests
ok 1 /fake/trigger-registers
ok 2 /fake/registers
ok 3 /fake/fake-device
ok 4 /fake/fake-device-error
ok 5 /fake/fake-stream
ok 6 /fake/camera-api
ok 7 /fake/camera-device
Bail out! ERROR:../tests/fake.c:592:set_features_from_string_test: assertion failed: (success)
stderr:
**
ERROR:../tests/fake.c:592:set_features_from_string_test: assertion failed: (success)
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――

6/6 aravis:network / fakegv OK 8.68s

Summary of Failures:

5/6 aravis:main / fake FAIL 1.60s killed by signal 6 SIGABRT

Ok: 5
Expected Fail: 0
Fail: 1
Unexpected Pass: 0
Skipped: 0
Timeout: 0

Full log written to /home/cam/download/aravis-0.8.10/build/meson-logs/testlog.txt
FAILED: meson-test
/usr/bin/meson test --no-rebuild --print-errorlogs
ninja: build stopped: subcommand failed.

てな感じで、失敗しますが、そのまま続けます。

cam@cam-desktop:~/download/aravis-0.8.10/build/gst$ に移動して、

一度、カメラのUSBを抜いて、再度差してから、

cam@cam-desktop:~/download/aravis-0.8.10/build/gst$ ./gst-aravis-launch aravissrc  ! "video/x-raw, format=GRAY8,width=640,height=480,framerate=4/1" ! videoconvert ! ximagesink

で、映像が出てきます。

image.png

ピント等がブレブレですが、遅延はほとんどないようです。

とりあえず、ホッとしています。

SRT通信もできるようです。

cam@cam-desktop:~/download/aravis-0.8.10/build/gst$ ./gst-aravis-launch aravissrc ! "video/x-raw, format=GRAY8,width=640,height=480,framerate=4/1" ! videoconvert ! x264enc tune=zerolatency key-int-max=30 ! mpegtsmux ! srtserversink uri="srt://:12345" latency=500

カラー表示も出てきました。

cam@cam-desktop:~/download/aravis-0.8.10/build/gst$ ./gst-aravis-launch aravissrc ! "video/x-raw, format=RGB ,width=640,height=480,framerate=30/1" ! videoconvert ! x264enc tune=zerolatency key-int-max=30 ! mpegtsmux ! srtserversink uri="srt://:12345" latency=500

2023,江端さんの忘備録

私は、気にいったモノは、とことん使い倒すタイプで、腕時計など、同じモノを3つ購入しています。

I am the type of person who uses up things I like to the fullest, and I have purchased three identical watches and other items.

一つは、(亡き)父にプレゼントしましたが、 ―― そうだとしても、3つは数が合いません(2つなら分かるのですが)。

One was a gift to my (late) father, but -- even if so, three doesn't count (although two would make sense).

この時計、電波時計で、文字が大きく、なにより安い(4000円弱)です。

This clock is radio-controlled, has large letters, and, most importantly, is inexpensive (less than 4,000 yen).

しかし、電池交換をすると2000円以上、バンド交換をしても同程度のコストがかかりますので、それを考えると、『使い捨て』が正しい用途なのだと思います。

However, replacing the battery costs more than 2,000 yen, and replacing the band costs about the same, so considering this, I think "disposable" is the correct use.

------

話を戻しまして、上記の「2つ」と「3つ」の違いなのですが、『電池切れになったので購入したものの、自分で電池交換したら動いてしまった』あたりがオチではないか、と思い、過去の日記を調べてみました。

Back to the story, the difference between the "two" and the "three" above, I thought it might be around "I bought another watch because the battery of the first watch ran out, but it worked after I changed the battery of the first by myself," so I checked my past diaries.

当たりでした。

It was a hit.

で、今回 ―― 「自分で電池交換してみようかな」と思いました。

で、私が、自力で電池交換やら、バンド交換している理由も、すでに記載していました。

And I have already mentioned why I am replacing batteries and bands alone.

―― 空腹で、気を失っている

-----

先日、1つが電池切れになって、もう一つがバンド切れになりましたので、それぞれ電池交換とバンド交換をしました。

One recently ran out of battery, and the other ran out of band, so I replaced the battery and band.

ゴムのバンドは、1年くらいで切れてしまうので、今回は、布のバンドに挑戦してみました。

The rubber bands would break after about a year, so I tried fabric bands this time.

送付されてきたものを見た時、『誤発注した』と思ったのですが、カスタマレビューを読みながら、このベルトの仕組みを理解しました。

When I saw what was sent to me, I thought, 'I ordered the wrong belt,' but as I read the customer reviews, I understood how this belt works.

「こういう仕組みのバンドなんだ」と納得して、無事にバンド交換を完了することができました。

I was convinced that "this is how the band works," and I completed the band replacement successfully.

-----

ボロボロで、液晶表示も欠けていて、各所を瞬間接着剤補強されている、私の可愛い大切な腕時計たちです。

They are my precious watches that are battered, missing LCDs and have been reinforced with superglue in various places.

『100万円のブランド時計と交換してくれ』と言われても、『だが、断わる』と言い切れます。

Even If someone says, 'Trade me a million yen for a brand-name watch,' I can say, 'But I refuse.'

-----

私の寿命と、この時計たちの寿命 ―― どっちが長いか? 勝負です。

My lifespan or the lifespan of these watches -- which is longer? It's a game.

私が死ぬ時に、この時計がまだ動いていたら ―― 私の勝ちです。

If this clock is still running when I die -- It is my win.

2023,江端さんの技術メモ

ラズパイ4は、(○arm64 ×amd64)を採用しており、色々とトラブルとなっています。これも、その一つかどうか不明ですが、Chromeのインストールに失敗しています。

で、まあ、以下のことをごちゃごちゃしているうちに動きましたので、メモを残しておきます。

$ sudo snap refresh
$sudo snap install chromium
( $ sudo apt install -y chromium-browser は、失敗しました)
で、起動は、
$ chromium (× $ chromium-browser)
でした。

以上

 


2023,江端さんの忘備録

10年ほど前に、家族にGmailのシステムを説明した時、『メールの本体は、クラウドに配置されている』という説明では通じませんでした。

When I explained the Gmail system to my family about ten years ago, the explanation that 'the body of the email is located in the cloud' did not get through.

そこで、こんな説明に変えました。

So I changed the explanation to this.

(1)『メールは、サンノゼ(カリフォルニアのシリコンバレー)にある会社のパソコンの中にあって、この自宅のパソコンの中にはない』

(1) "Your email is in a computer in San Jose (Silicon Valley, California), not in this home computer."

(2)『このパソコンは、アメリカにあるパソコンの中の中身を写しているだけ』

(2) "This computer is just a copy of the contents inside the computer in the U.S."

(3)『だから、このパソコンでも、名古屋のパソコンでも、鹿児島のパソコンでも、スマホでも、同じメールを見ることができる』

(3) "So, I can see the same email on this computer, on a computer in Nagoya, on a computer in Kagoshima, and on my smartphone."

-----

つまり、「クラウドとは何か」と問われたら、いらんこと言わずに「外国にあるパソコンだ」と答えれば良いと思います。

In other words, if someone asks you, "What is the cloud?" you can answer, "It's a computer in a foreign country," without saying anything unnecessary.

東京リージョンだの、大阪リージョンだの、仮想化だの、コンテナだの、そういうことを『言わなこと』がコツです。

The trick is not to "say" Tokyo Region, Osaka Region, virtualization, containers, etc.

今、娘たちは、「クラウド」という言葉を日常的に使っていますが、多分、実態としての理解しているかは不明です。

My daughters now use the term "cloud" daily, but I am unsure if they understand it as a reality.

言語化することで、分かったような気になるのは、仕方がないことです。

By verbalizing it, we inevitably feel like we know it.

でも、時々は、ちゃんと考えてみる必要はあると思います。

But we need to think things through from time to time.

-----

この「クラウド」と似ているものが「AI」です。

Similar to this "cloud" is "AI.

「AI」が、なんでもできる凄いもの、と考えるのは仕方がないことですが、やはり時々は、ちゃんと考えてみる必要はあると思います。

It is inevitable to think of "AI" as a great thing that can do everything, but it is still necessary to think about it properly occasionally.

以前、私はAI技術についての連載をやっていました。

I used to write a series of articles on AI technology.

また先日は、ChatGPTについてのコラムを寄稿しました。

I also recently contributed a column on ChatGPT.

で、この結果分かったことは、

And what I found out as a result of this,

―― AI技術は、先生(人間)の言うことをきちんと聞いて、もの凄い時間(数億~数兆回の反復学習)をかけて『ガリ勉』をすることで、完成している

-- AI technology is perfected by listening to the teacher (human) and spending a tremendous amount of time (hundreds of millions to trillions of iterations) "studying hard."

という事実です。

近年のAI技術は、「優れたロジック」や「スマートなアルゴリズム」の効果として語られなくなりつつあります。

In recent years, AI technology is no longer considered the effect of "good logic" or "smart algorithms."

逆に、『真摯に指導を受ける姿勢』と『ガリ勉』のみが、最強AI技術の根幹であることを、力強く主張しています。

On the contrary, they argue that only a 'sincere attitude toward instruction' and 'skinny-dipping' are the foundation of the most powerful AI technology.

-----

こういう人生訓めいたことを、教えられるのは、正直愉快ではありませんが ――

I have to admit that I don't enjoy being taught this kind of life lesson, however,

『何かをなすためには"学習を繰り返し続けること"が必要である』

"To do something, I have to keep learning repeatedly."

ことを、私は、AI技術から教わりました。

I learned that from AI technology.

私の提案する方法は、我が国のお国芸である『同調圧力』です。

2023,江端さんの技術メモ

Pythonを使った因子分析のコード を そのまま使わせて頂いています。
【Pythonで行う】因子分析

# ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/go-efa$ python3 main3.py

# ライブラリのインポート
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
from factor_analyzer import FactorAnalyzer

# データの読み込み
df_workers = pd.read_csv("sample_factor.csv")
print(df_workers)

# 変数の標準化
df_workers_std = df_workers.apply(lambda x: (x-x.mean())/x.std(), axis=0)

# 固有値を求める
ei = np.linalg.eigvals(df_workers.corr())
print("固有値", ei)

# 因子分析の実行
fa = FactorAnalyzer(n_factors=2, rotation="promax")
fa.fit(df_workers_std)

# 因子負荷量,共通性
loadings_df = pd.DataFrame(fa.loadings_, columns=["第1因子", "第2因子"])
loadings_df.index = df_workers.columns
loadings_df["共通性"] = fa.get_communalities()
print(loadings_df)

# 因子負荷量の二乗和,寄与率,累積寄与率
var = fa.get_factor_variance()
df_var = pd.DataFrame(list(zip(var[0], var[1], var[2])), 
                      index=["第1因子", "第2因子"], 
                      columns=["因子負荷量の二乗和", "寄与率", "累積寄与率"])
print(df_var.T)

# バイプロットの作図
score = fa.transform(df_workers_std)
coeff = fa.loadings_.T
fa1 = 0
fa2 = 1
labels = df_workers.columns
annotations = df_workers.index
xs = score[:, fa1]
ys = score[:, fa2]
n = score.shape[1]
scalex = 1.0 / (xs.max() - xs.min())
scaley = 1.0 / (ys.max() - ys.min())
X = xs * scalex
Y = ys * scaley
for i, label in enumerate(annotations):
    plt.annotate(label, (X[i], Y[i]))
for j in range(coeff.shape[1]):
    plt.arrow(0, 0, coeff[fa1, j], coeff[fa2, j], color='r', alpha=0.5, 
              head_width=0.03, head_length=0.015)
    plt.text(coeff[fa1, j] * 1.15, coeff[fa2, j] * 1.15, labels[j], color='r', 
             ha='center', va='center')
plt.xlim(-1, 1)
plt.ylim(-1, 1)
plt.xlabel("第1因子")
plt.ylabel("第2因子")
plt.grid()
plt.show()

Pythonを使ったGAのコード を そのまま使わせて頂いています。

【python】遺伝的アルゴリズム(Genetic Algorithm)を実装してみる

遺伝配列を0/1を、便宜的に0~4にして動くよう、一部改造させて頂いております。

# ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/go-efa$ python3 ga.py

import numpy as np
import matplotlib.pyplot as plt

class Individual:
    '''各個体のクラス
        args: 個体の持つ遺伝子情報(np.array)'''
    def __init__(self, genom):
        self.genom = genom
        self.fitness = 0  # 個体の適応度(set_fitness関数で設定)
        self.set_fitness()

    def set_fitness(self):
        '''個体に対する目的関数(OneMax)の値をself.fitnessに代入'''
        self.fitness = self.genom.sum()

    def get_fitness(self):
        '''self.fitnessを出力'''
        return self.fitness

    def mutate(self):
        '''遺伝子の突然変異'''
        tmp = self.genom.copy()
        i = np.random.randint(0, len(self.genom) - 1)
        # tmp[i] = float(not self.genom[i]) 
        tmp[i] = np.random.randint(0, 5) #  江端修正
        self.genom = tmp
        self.set_fitness()


def select_roulette(generation):
    '''選択の関数(ルーレット方式)'''
    selected = []
    weights = [ind.get_fitness() for ind in generation]
    norm_weights = [ind.get_fitness() / sum(weights) for ind in generation]
    selected = np.random.choice(generation, size=len(generation), p=norm_weights)
    return selected


def select_tournament(generation):
    '''選択の関数(トーナメント方式)'''
    selected = []
    for i in range(len(generation)):
        tournament = np.random.choice(generation, 3, replace=False)
        max_genom = max(tournament, key=Individual.get_fitness).genom.copy()
        selected.append(Individual(max_genom))
    return selected


def crossover(selected):
    '''交叉の関数'''
    children = []
    if POPURATIONS % 2:
        selected.append(selected[0])
    for child1, child2 in zip(selected[::2], selected[1::2]):
        if np.random.rand() < CROSSOVER_PB:
            child1, child2 = cross_two_point_copy(child1, child2)
        children.append(child1)
        children.append(child2)
    children = children[:POPURATIONS]
    return children


def cross_two_point_copy(child1, child2):
    '''二点交叉'''
    size = len(child1.genom)
    tmp1 = child1.genom.copy()
    tmp2 = child2.genom.copy()
    cxpoint1 = np.random.randint(1, size)
    cxpoint2 = np.random.randint(1, size - 1)
    if cxpoint2 >= cxpoint1:
        cxpoint2 += 1
    else:
        cxpoint1, cxpoint2 = cxpoint2, cxpoint1
    tmp1[cxpoint1:cxpoint2], tmp2[cxpoint1:cxpoint2] = tmp2[cxpoint1:cxpoint2].copy(), tmp1[cxpoint1:cxpoint2].copy()
    new_child1 = Individual(tmp1)
    new_child2 = Individual(tmp2)
    return new_child1, new_child2


def mutate(children):
    for child in children:
        if np.random.rand() < MUTATION_PB:
            child.mutate()
    return children


def create_generation(POPURATIONS, GENOMS):
    '''初期世代の作成
        return: 個体クラスのリスト'''
    generation = []
    for i in range(POPURATIONS):
        # individual = Individual(np.random.randint(0, 2, GENOMS))
        individual = Individual(np.random.randint(0, 5, GENOMS))
        generation.append(individual)
    return generation


def ga_solve(generation):
    '''遺伝的アルゴリズムのソルバー
        return: 最終世代の最高適応値の個体、最低適応値の個体'''
    best = []
    worst = []
    # --- Generation loop
    print('Generation loop start.')
    for i in range(GENERATIONS):
        # --- Step1. Print fitness in the generation
        best_ind = max(generation, key=Individual.get_fitness)
        best.append(best_ind.fitness)
        worst_ind = min(generation, key=Individual.get_fitness)
        worst.append(worst_ind.fitness)
        print("Generation: " + str(i) \
                + ": Best fitness: " + str(best_ind.fitness) \
                + ". Worst fitness: " + str(worst_ind.fitness))

        # --- Step2. Selection (Roulette)
        # selected = select_roulette(generation)
        selected = select_tournament(generation)

        # --- Step3. Crossover (two_point_copy)
        children = crossover(selected)

        # --- Step4. Mutation
        generation = mutate(children)

    print("Generation loop ended. The best individual: ")
    print(best_ind.genom)
    return best, worst


np.random.seed(seed=65)

# param
POPURATIONS = 100
# GENOMS = 50 # 江端修正
GENOMS = 160
GENERATIONS = 1000
CROSSOVER_PB = 0.8
MUTATION_PB = 0.1

# create first genetarion
generation = create_generation(POPURATIONS, GENOMS)

# solve
best, worst = ga_solve(generation)

# plot
fig, ax = plt.subplots()
ax.plot(best, label='max')
ax.plot(worst, label='min')
ax.axhline(y=GENOMS, color='black', linestyle=':', label='true')
ax.set_xlim([0, GENERATIONS - 1])
#ax.set_ylim([0, GENOMS * 1.1])
ax.set_ylim([0, GENOMS * 2.2])
ax.legend(loc='best')
ax.set_xlabel('Generations')
ax.set_ylabel('Fitness')
ax.set_title('Tournament Select')
plt.show()

 

明日は、この2つをマージして、目的のプログラムを完成させます。

以下のプログラムは、20個のデータを使って因子分析を行い、その分析因子分析を同じ結果を生み出す200個のダミーデータを作成します。

アルゴリズムの説明は省略します(が、私は分かっています)。

まず、データ(sample_factory.csv)

x1,x2,x3,x4,x5,x6,x7,x8
2,4,4,1,3,2,2,1
5,2,1,3,1,4,2,1
2,3,4,3,4,2,4,5
2,2,2,2,3,2,2,2
5,4,3,4,4,5,4,3
1,4,4,2,4,3,2,3
3,1,1,1,1,2,1,1
5,5,3,5,4,5,3,5
1,3,4,1,3,1,3,1
4,4,3,1,4,4,2,1
3,3,3,2,4,4,4,2
1,2,1,3,1,1,1,1
5,2,3,5,2,5,1,3
4,1,1,3,1,2,2,1
1,1,1,1,2,1,2,1
3,1,2,1,1,3,2,1
1,2,3,5,2,2,2,2
3,1,1,3,2,4,2,1
3,2,3,2,2,2,2,5
1,4,3,1,4,3,5,3

以下、GAのコード

# ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/go-efa$ python3 ga-factory2.py

# ライブラリのインポート
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# import japanize_matplotlibe
from factor_analyzer import FactorAnalyzer
import matplotlib.pyplot as plt

class Individual:
    '''各個体のクラス
        args: 個体の持つ遺伝子情報(np.array)'''
    def __init__(self, genom):
        self.genom = genom
        self.fitness = 0  # 個体の適応度(set_fitness関数で設定)
        self.set_fitness()

    def set_fitness(self):
        '''個体に対する目的関数(OneMax)の値をself.fitnessに代入'''
        # まずgenomを行列にデータに変換する
        # self.fitness = self.genom.sum()

        # 遺伝子列を行列に変換
        arr2d = self.genom.reshape((-1, 8)) # 列が分からない場合は、-1にするとよい

        # 各列の平均と標準偏差を計算
        mean = np.mean(arr2d, axis=0)
        std = np.std(arr2d, axis=0)

        # 標準偏差値に変換
        standardized_arr2d = (arr2d - mean) / std

        # 因子分析の実行
        fa_arr2d = FactorAnalyzer(n_factors=2, rotation="promax")
        fa_arr2d.fit(standardized_arr2d)

        # 因子分析行列の算出
        loadings_arr2d = fa_arr2d.loadings_

        # 因子分析行列の差分算出
        distance2 = euclidean_distance(fa.loadings_, loadings_arr2d)
        # print(distance2)
        
        # とりあえず評価関数をこの辺から始めてみる
        self.fitness = 1 / distance2

    def get_fitness(self):
        '''self.fitnessを出力'''
        return self.fitness

    def mutate(self):
        '''遺伝子の突然変異'''
        tmp = self.genom.copy()
        i = np.random.randint(0, len(self.genom) - 1)
        # tmp[i] = float(not self.genom[i]) 
        tmp[i] = np.random.randint(1, 6) #  江端修正
        self.genom = tmp
        self.set_fitness()


def euclidean_distance(matrix_a, matrix_b):
    # 行列Aと行列Bの要素ごとの差を計算します
    diff = matrix_a - matrix_b
    
    # 差の二乗を計算します
    squared_diff = np.square(diff)
    
    # 差の二乗の和を計算します
    sum_squared_diff = np.sum(squared_diff)
    
    # 和の平方根を計算します
    distance = np.sqrt(sum_squared_diff)
    
    return distance


def select_roulette(generation):
    '''選択の関数(ルーレット方式)'''
    selected = []
    weights = [ind.get_fitness() for ind in generation]
    norm_weights = [ind.get_fitness() / sum(weights) for ind in generation]
    selected = np.random.choice(generation, size=len(generation), p=norm_weights)
    return selected


def select_tournament(generation):
    '''選択の関数(トーナメント方式)'''
    selected = []
    for i in range(len(generation)):
        tournament = np.random.choice(generation, 3, replace=False)
        max_genom = max(tournament, key=Individual.get_fitness).genom.copy()
        selected.append(Individual(max_genom))
    return selected


def crossover(selected):
    '''交叉の関数'''
    children = []
    if POPURATIONS % 2:
        selected.append(selected[0])
    for child1, child2 in zip(selected[::2], selected[1::2]):
        if np.random.rand() < CROSSOVER_PB:
            child1, child2 = cross_two_point_copy(child1, child2)
        children.append(child1)
        children.append(child2)
    children = children[:POPURATIONS]
    return children


def cross_two_point_copy(child1, child2):
    '''二点交叉'''
    size = len(child1.genom)
    tmp1 = child1.genom.copy()
    tmp2 = child2.genom.copy()
    cxpoint1 = np.random.randint(1, size)
    cxpoint2 = np.random.randint(1, size - 1)
    if cxpoint2 >= cxpoint1:
        cxpoint2 += 1
    else:
        cxpoint1, cxpoint2 = cxpoint2, cxpoint1
    tmp1[cxpoint1:cxpoint2], tmp2[cxpoint1:cxpoint2] = tmp2[cxpoint1:cxpoint2].copy(), tmp1[cxpoint1:cxpoint2].copy()
    new_child1 = Individual(tmp1)
    new_child2 = Individual(tmp2)
    return new_child1, new_child2


def mutate(children):
    for child in children:
        if np.random.rand() < MUTATION_PB:
            child.mutate()
    return children


def create_generation(POPURATIONS, GENOMS):
    '''初期世代の作成
        return: 個体クラスのリスト'''
    generation = []
    for i in range(POPURATIONS):  # POPURATIONS = 100
        # individual = Individual(np.random.randint(0, 2, GENOMS))
        individual = Individual(np.random.randint(1, 6, GENOMS))
        generation.append(individual)
    return generation


def ga_solve(generation):
    '''遺伝的アルゴリズムのソルバー
        return: 最終世代の最高適応値の個体、最低適応値の個体'''
    best = []
    worst = []
    # --- Generation loop
    print('Generation loop start.')
    for i in range(GENERATIONS):
        # --- Step1. Print fitness in the generation
        best_ind = max(generation, key=Individual.get_fitness)
        best.append(best_ind.fitness)
        worst_ind = min(generation, key=Individual.get_fitness)
        worst.append(worst_ind.fitness)
        print("Generation: " + str(i) \
                + ": Best fitness: " + str(best_ind.fitness) \
                + ". Worst fitness: " + str(worst_ind.fitness))

        # --- Step2. Selection (Roulette)
        # selected = select_roulette(generation)
        selected = select_tournament(generation)

        # --- Step3. Crossover (two_point_copy)
        children = crossover(selected)

        # --- Step4. Mutation
        generation = mutate(children)

    print("Generation loop ended. The best individual: ")
    print(best_ind.genom)
    return best, worst



np.random.seed(seed=65)

# param
POPURATIONS = 100  # 個体数
# GENOMS = 50 # 江端修正

# GENOMS = 160 # GENの長さ
GENOMS = 1600 # GENの長さ 1つのデータが8個の整数からなるので、合計200個のデ0タとなる 

GENERATIONS = 1000
CROSSOVER_PB = 0.8

# MUTATION_PB = 0.1 
MUTATION_PB = 0.3 # ミューテーションは大きい方が良いように思える

# ファイルからデータの読み込み
df_workers = pd.read_csv("sample_factor.csv")
print(df_workers)

# 変数の標準化
df_workers_std = df_workers.apply(lambda x: (x-x.mean())/x.std(), axis=0)
print(df_workers_std)


# 固有値を求める(不要と思うけど、残しておく)
ei = np.linalg.eigvals(df_workers.corr())
print(ei)

print("因子分析の実行") # 絶対必要
fa = FactorAnalyzer(n_factors=2, rotation="promax")
fa.fit(df_workers_std)

# print(fa.loadings_) # これが因子分析の行列


# 因子負荷量,共通性(不要と思うけど、残しておく)
loadings_df = pd.DataFrame(fa.loadings_, columns=["第1因子", "第2因子"])
loadings_df.index = df_workers.columns
loadings_df["共通性"] = fa.get_communalities()

# 因子負荷量の二乗和,寄与率,累積寄与率(不要と思うけど、残しておく)
var = fa.get_factor_variance()
df_var = pd.DataFrame(list(zip(var[0], var[1], var[2])), 
                      index=["第1因子", "第2因子"], 
                      columns=["因子負荷量の二乗和", "寄与率", "累積寄与率"])
print(df_var.T)



# create first genetarion
generation = create_generation(POPURATIONS, GENOMS)

# solve
best, worst = ga_solve(generation)

# plot

#fig, ax = plt.subplots()
#ax.plot(best, label='max')
#ax.plot(worst, label='min')
#ax.axhline(y=GENOMS, color='black', linestyle=':', label='true')
#ax.set_xlim([0, GENERATIONS - 1])
#ax.set_ylim([0, GENOMS * 1.1])
#ax.legend(loc='best')
#ax.set_xlabel('Generations')
#ax.set_ylabel('Fitness')
#ax.set_title('Tournament Select')
#plt.show()

ga-factory2.py :200固体  主成分行列からの距離は、distance2(これが一致度) 評価関数は、この逆数を使っているだけ

ga-factory3.py :2000固体

以上

 

2023,江端さんの技術メモ

PythonからGo、GoからPythonを呼び出し合う

で、勉強させて頂いております。

私、今、超スケーラブルな高速の遺伝的アルゴリズムをGo言語で実装しようとしているのですが、計算ライブラリの充実度はPythonが圧倒しているからです。

# 私が、Go言語で計算ライブラリを自作する、というのは、却下です(面倒くさい)

まあ、これは、元を辿ると"ChatGPTの責任"とも言えるのですが(押しつけ)

『ChatGPTは、もの凄く真摯な言葉で、嘘をつく』

取り敢えず、参照させて頂いたページのコードを、自分の環境に合わせて(といっても、結構苦労した"Python3.h"の場所が分からなかった)、ここまで動きました。

/* 
   環境
   wsl -d Ubuntu-20.04

   実行結果
   ebata@DESKTOP-P6KREM0:/mnt/c/Users/ebata/go-efa$ go run main1.go
   Hello, World! and Ebata is great
*/

package main

// #cgo CFLAGS: -I/usr/include/python3.9
// #cgo LDFLAGS: -L/usr/lib/pytho3.9 -lpython3.9
// #include 
import "C"
// import "C"のうえに改行いれるとエラーになる(信じられないが)

func main() {
    //  最後にPythonインタプリタ終了
    defer C.Py_Finalize()
    // Pythonインタプリタの初期化
    C.Py_Initialize()
    // GoのstringをCのcharに型変換(変換しないとPyRun_SimpleStringに型合ってないよって怒られる)
    // cannot use "print(\"Hello, World!\")" (type string) as type *_Ctype_char in argument to _Cfunc_PyRun_SimpleString
    pyCodeStr := `print("Hello, World! and Ebata is great!")`
    pyCodeChar := C.CString(pyCodeStr)
    // Pythonコードを文字列として受け取ってインタプリタ上で実行
    C.PyRun_SimpleString(pyCodeChar)

}

ようするに、このプログラムは、Go言語を使って、Pythonのインタプリタに一行づつコマンドを打ち込むプログラムのようです。

pythonのライブラリを使えるという訳でないようです。

GoとPythonをマージする方法は、どうも調子がよくないようです。

GoとPythonとGrumpyの速度ベンチマーク ~Googleのトランスパイラはどれくらい速い?~

 

2023,江端さんの忘備録

「愚者は経験に学び、賢者は歴史に学ぶ」は、ビスマルクの格言ですが、

"Fools learn from experience, and wises learn from history" was Bismarck's maxim, however,

―― もはや、賢者も歴史から学ぶことはできないんじゃないかなぁ

"I wonder if the wise can no longer learn from history."

という気がしています。

I come to think so.

すぐに思う浮ぶのは「コロナ」と「ウクライナ」です。

The two that immediately come to mind are "Corona" and "Ukraine."

全く、予想もできない事態が起きて、私のような素人はもちろん、いわゆる専門家と言われている人ですら、予測の範囲内にないことが発生し続いてきましたし、続けています。

Unpredictable events that are not within the scope of prediction of even so-called experts, let alone laypeople like myself, have occurred and continue to happen.

例えば ―― 『我が国は、とっとと白旗を上げて降参していれば良かった』という、太平洋戦争における米国との戦争についての私の歴史認識は、今、現在進行形で『本当にそうだったのかな?』と思わせるに至っています。

For example -- "My historical perception of the war with the United States in the Pacific War, that 'Our country should have just raised the white flag and surrendered,' is now ongoing, leading me to wonder, 'Was that the case?'"

歴史に学ぶのであれば、こんな疑問は発生してこないはずです。

If I were to learn from history, such questions would not arise.

(まあ、軍事大国が必ずしも勝利しないことは、ベトナムやアフガニスタンでの米国を見れは明かですが)

(The military superpower doesn't always win, as evidenced by the U.S. in Vietnam and Afghanistan.)

まあ、現在のウクライナと当時の日本では、状況は違い過ぎますが、その状況も含めて、『経験からも歴史からも、正解は導き出せない』と思うのです。

The situation in Ukraine today is too different from that in Japan. Still, including that situation, I think 'the right answer cannot be derived from experience or history.

というか、『そもそも正解はあるのか?』

Or rather, 'Is there a right answer to begin with?'

-----

来年あたり、この日記を読み直して、『なんで、私は、こんな抽象的かつ哲学的な語りをしてりるんだ?』 と、頭の中に疑問符が浮んぶあるだろうと思い、一応、キーワードを残しておきます。

I'll leave you with a few keywords in case you reread this diary next year and wonder, "Why am I talking in such an abstract and philosophical way?" so I will leave some keywords here in case there will be a question mark in your mind.

"ワグネル反乱"

"The Wagner Rebellion."

"内乱に国際法は適用されるのか?"(*1)

"Does International Law Apply to Civil War?" (*1)

(*)https://www.cao.go.jp/pko/pko_j/organization/researcher/atpkonow/article063.html

どうやら、『現時点では、国家主権を超越する主体は存在しない(*2)』―― らしいです。

"At present, no entity transcends national sovereignty" (*2).

(*2)https://www.icrc.org/en/doc/assets/files/other/irrc-873-vite.pdf

-----

「世界中を敵に回しても」・・・? 世界中って、米軍も?

「世界中を敵に回しても」・・・? 世界中って、みたいに?

2023,江端さんの忘備録

私が、社会人大学院で、必死に調査研究をしているきっかけの一つが、『マージナル・オペレーション』である、と言ったら驚かれるかもしれませんが ―― これは事実です。

You may be surprised to hear me say that one of the reasons I am working so hard to research in a working graduate school is because of "Marginal Operations" -- this is true.

もっとも、その対象は、紛争や政治ではなく、通信デバイス(のワンオペ運用)です。

However, my concern is not conflict or politics but the one-operation of telecommunication devices.

ペーパーには、この本の引用も謝辞も記載していません(そんなことしたら、レビューアーがビックリするだろう)。

I have not included a citation or acknowledgment of the book in my paper (reviewers would be surprised if I did that).

ですが、もし、ちゃんと卒業できたら、芝村裕吏さんに御礼の手紙を差し上げよう、という気持ちはあります。

However, if I can graduate properly, I would like to send a letter of thanks to Mr. Yuri Shibamura.

バス、タクシー、鉄道の運行管理や予約管理では「戦闘」は発生しませんから、オペレーションの負荷は、随分小さくなるはずです。

-----

『マージナル・オペレーション』のシリーズは、私の居所の市民図書館がガッチリ蔵書していて、こちらから借りております。

The "Marginal Operations" series is held by the civic library where I live, and I have been borrowing it from there.

本を購入しないのは、お金が惜しのでなく、(私の自宅の)スペースが惜しいからです。

I don't buy books, not because I am sparing money, but because I am sparing space (in my home).

それでも、いつかはちゃんと紙の本を手元に置きたいと思って、電子書籍の購入は思い留まっています。

Still, I am holding off purchasing an e-book because I want a good paper book someday.

ともあれ、私の居所の図書館は、良い図書館です。

Anyway, the library where I live is good.

NHKと正面きってバトルを展開する胆力のある、我が街の誇るべき図書館です。

We are proud of our city's library, which has the gall to engage in a head-to-head battle with NHK.

-----

この図書館に『マージナル・オペレーション』シリーズの全部を揃えて貰うのを期待するは、私の傲慢というものです。

It would be arrogant of me to expect this library to have the entire "Marginal Operations" series.

今回、図書館に蔵書していなかった2冊を、久々にAmazonで購入しました。

This time, I purchased two books from Amazon.com that had not been in the library's collection for some time.

『喰い散らかすように読んではダメだぞ』と自分に言い聞かせていたのですが ―― 大学への往復(1日)で、2冊を読み終えてしまいました。

I told myself, 'Don't read it like going to eat it all up' -- but I finished two books on my way to and from the university in a day.

-----

―― こんな読み方はよくない

"Not a good manner to read this"

―― これからは、特許明細書、研究報告書、論文提出の後の「ご褒美」として、読むようにしよう

"From now on, I will read the series as a "reward" after submitting patent specifications, research reports, and papers."

と、改めて誓いました。

I vowed once again to do so.

2023,江端さんの忘備録

映像システムを構築する情報を求めて、13時から、実に10時間以上システムと格闘し続けました。

I have been struggling with the system for over 10 hours since 1:00 p.m. today in search of information to build a video system.

先程、中国語で書かれた、たった2行の情報から、システムの稼動に漕ぎつけました。

I have just gotten the system up and running based on just two lines of information written in Chinese.

(ちなみに、中国語は翻訳エンジンで解読しました)

(Incidentally, the Chinese were deciphered by a translation engine)

言うまでもありませんが、ChaGPTのほかに様々なツールを使い倒した上で、このザマです。

This is the case after using various tools in addition to ChaGPT.

『10時間あれば、一体どれだけのことができただろうか』 ―― などと考えたら、この仕事は『負け』です。

"How much could I have done with 10 hours?" If you think like that, you will 'lose' this field.

-----

システムやプログラミングは楽しいですが、専門性や特殊性が上がれば上がるほど、消費される時間がどんどん長くなっていきます。

Systems and programming are fun, but the more specialized and specific they become, the more and more time they consume.

費用対効果で考えるとどうなのかな、と考えてしまいます。

It makes me wonder how it would be cost-effective.

「中国語で書かれた、たった2行の情報を見つけ出す」ことに、いくらの値段が付けられるのか、私にも分かりません。

I don't know what price we can put on "finding just two lines of information written in Chinese."

-----

我が国にとって、デジタル化やプログラム教育は、避けては通れない道です。

For our country, digitization and programmed education are the inevitable paths.

マイナンバカード、絶賛問題噴出中ですが、私には、システム初期稼動時の避けて通れない「バグ出し」期間に見えます。

My number card, which has been causing many problems, seems to me to be an inevitable "bug out" period during the initial operation of the system.

もちろん、被害にあった人に対して、政府とベンダは、真摯な謝罪と相応の補償をしていく必要はありますが、マイナンバカードシステムを全面停止させる、という選択はありえないでしょう。

Of course, the government and vendors must offer sincere apologies and reasonable compensation to those affected. Still, there will be no choice but to shut down the MyNumber card system altogether.

なんやかんやいって『マイナンバーカード = 国民監視システム』というのは事実です。

After all, it is a fact that "My Number Card = National Surveillance System."

しかし、今やそのデメリットは『含み損益』くらいの重さしかありません。

But now its disadvantages are only as heavy as 'unrealized gains.'

これまでのような、ちんたらとした手動業務処理などと続けていたら、少子高齢化の巻き添えくらって、我が国は、明治維新レベルまで行政処理が退後するだろう ―― と、本気で私は思っています。

I seriously believe that if we continue with the slow and tedious manual processing of work as we have done up to now, the declining birthrate and aging population will drag our country down. Our administrative processes will be returned to the Meiji Restoration level.

ちなみに、我が国は、ビッグブラザーの監視社会として完成しています。いまさらジタバタしても遅いのです。

Incidentally, our country is completed as a Big Brother surveillance society. It is too late to be jittery now.

―― 一体、裁判所も、立法(国会)も、『識別子の取扱い』ごときに、なんで、こんなにゴタゴタしていやがるんだ

それどころか、私個人としては、ビッグブラザーの側の人間として協力したことすらあります ―― いわゆる、『権力の犬』です。

On the contrary, I have collaborated on Big Brother's side -- as the so-called "dogs of power."

長女から、「ついに"権力の犬"に成り下がったか」という感じで、問い詰められました。

-----

ともあれ、デジタル化やプログラム教育は、

Through digitization and programmed education, I believe that

『システムの不具合に「文句を言う」側の国民を、ごそっと、システムの不具合に「文句を言われる』側に異動させる』

"digitization and programming education will move many people who complain about system failures to the side of those who are complained about system failures."

ことになると思います。

『10時間かけて、たった2行の改修』という世界に、沢山の人間が投入されて、悲鳴を上げている地獄絵図を考えると

When I think of the hellish picture of so many people being put into the world of "10 hours of work and only two lines of renovation" and screaming,

―― 心底から楽しい

That makes me happy with all my heart.

2023,江端さんの技術メモ

Raspberry Pi Ubuntu Spinnaker SDK Setup
Raspberry Pi Ubuntu Spinnaker SDKのセットアップ

These steps describe using an Ubuntu desktop environment to install Ubuntu and the Spinnaker Python interface on a Raspberry Pi 3 B+. Commands to be run on the desktop are prefaced with (desktop)$, and commands to be run on the Raspberry Pi are prefaced with (pi)$

この手順では、Ubuntuデスクトップ環境を使用して、Raspberry Pi 3 B+にUbuntuとSpinnaker Pythonインターフェースをインストールする方法を説明します。デスクトップ上で実行するコマンドの前には(desktop)$を、Raspberry Pi上で実行するコマンドの前には(pi)$を付けます。

  1. Flash the latest Ubuntu image (at the time of writing: 18.04) to an SD card and perform first-time setup by following these instructions. You will need an HDMI cable, a monitor, and a keyboard. The Raspberry Pi must also be connected to your local network via Ethernet.
    最新のUbuntuイメージ(執筆時点では18.04)をSDカードに書き込み、以下の手順に従って初回セットアップを行う。HDMIケーブル、モニター、キーボードが必要です。また、Raspberry Piはイーサネット経由でローカルネットワークに接続されている必要があります。

  2. Perform basic software updates on the Pi:
    Piの基本的なソフトウェアアップデートを行う:
    (pi)$ sudo apt update && sudo apt upgrade
  3. Go to the FLIR File Download website for your camera. The software downloads will require a free FLIR account.
    お使いのカメラのフリアーファイルダウンロードサイトにアクセスします。ソフトウェアのダウンロードにはフリアーシステムズの無料アカウントが必要です。

  4. On the FLIR website, find the latest Linux Ubuntu ARM Operating System packages.
    フリアーシステムズのウェブサイトで、最新のLinux Ubuntu ARMオペレーティングシステムパッケージをご覧ください。

  5. Download the ARM64 packages for the Spinnaker SDK and Spinnaker Python Interface, and transfer them to the Raspberry Pi. Eg:
    Spinnaker SDK と Spinnaker Python Interface の ARM64 パッケージをダウンロードし、Raspberry Pi に転送します。例

    (pi)$ ip a # check pi's ip address
    (desktop)$ scp spinnaker-*-pkg.tar.gz spinnaker_python-*.tar \
     ubuntu@<pi's ip address>:~
  6. On the Raspberry Pi, untar the spinnaker sdk and enter the untarred directory
    Raspberry Pi上で、spinnaker sdkをuntarし、untarしたディレクトリに入ります。
  7. Read the README file fully, then run the install script. Eg:
    READMEファイルを十分に読んでから、インストールスクリプトを実行してください。例

    (pi)$ sudo sh install_spinnaker_arm.sh
  8. You will probably run into some dependency issues while installing the SDK. If that’s the case, missing packages can be installed manually with:
    SDKのインストール中に依存関係の問題に遭遇することもあるでしょう。その場合、不足しているパッケージを手動でインストールすることができます:

    (pi)$ sudo apt install <name-of-missing-package>
    
    
  9. Change back to your home directory, untar the python interface, then untar the python 3.6 interface.
    ホームディレクトリに戻り、pythonインターフェースをuntarし、python 3.6インターフェースをuntarする。

    (pi)$ tar -xf spinnaker_python-1.*.tar
    (pi)$ tar -xf spinnaker_python-1.*cp36*.tar.gz 
  10. Read the README.txt fully, then install numpy and the Spinnaker python interface. At the time of writing, there are no precompiled wheels for numpy on Ubuntu ARM, so pip will compile the package from souce. This will take several hours, but can be sped up a bit by increasing the Pi's swap size.
    README.txtを十分に読み、numpyとSpinnaker pythonインターフェースをインストールします。この記事を書いている時点では、Ubuntu ARMにはnumpy用のプリコンパイルホイールがないので、pipがソースからパッケージをコンパイルします。これには数時間かかりますが、Piのスワップサイズを大きくすることで少しスピードアップできます。

    (pi)$ sudo apt install dphys-swapfile # (optional)
    # follow the rest of the increasing swap size tutorial (optional)
    (pi)$ sudo apt install python3-pip
    (pi)$ python3 -m pip install numpy
    (pi)$ sudo python3 -m pip install spinnaker_python-1.*.whl
  11. Ensure the python module can be imported successfully:
    pythonモジュールが正常にインポートできることを確認する:

    (pi)$ python3 -c 'import PySpin' # should take a few seconds, then exit silently

    You will probably run into more dependency issues here. When you try to import PySpin with a missing dependency, you'll get an error along the lines of No Such File: <name-of-missing-package>.so. See step 8 for help resolving these issues.
    おそらくここで依存関係の問題にもっとぶつかるでしょう。依存関係が見つからないPySpinをインポートしようとすると、No Such File: <名前-of-missing-package>.soというエラーが表示されます。このような問題の解決についてはステップ8を参照してください。

  12. Increase the space allocated to USB devices on the Pi. This is needed so that the images taken by the camera can fit properly within RAM. Note: This change will not persist through reboot and must be repeated.
    PiのUSBデバイスに割り当てられる容量を増やす。これは、カメラで撮影された画像がRAM内に適切に収まるようにするために必要です。注意: この変更は再起動しても維持されないので、繰り返し行う必要があります。

    (pi)$ sudo sh -c 'echo 256 > /sys/module/usbcore/parameters/usbfs_memory_mb'
  13. Connect your USB 3.1 FLIR camera to the Raspberry Pi via USB.
    USB3.1フリアーシステムズのカメラをUSB経由でRaspberry Piに接続します。

  14. Change into the Examples directory for PySpin, and run the Acquisition.py example as root. If this succeeds, the camera will take 10 pictures and store them as JPEGs in the current directory.
    PySpinのExamplesディレクトリに移動し、rootでAcquisition.pyを実行します。これが成功すると、カメラは10枚の写真を撮影し、JPEGとしてカレントディレクトリに保存します。

    (pi)$ cd Examples/Python3
    (pi)$ sudo python3 Acquisition.py