2023,江端さんの忘備録

Pythonは、統計計算ライブラリが充実しています。

Python has an extensive statistical computing library.

『いきなり何の話 ?』と思われるかもしれませんが、この話の続きになります。

You may be thinking, "What is Ebata starting to talk about?

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

『ChatGPTは嘘をつく』どころか、Pythonの統計ライブラリのコードに関して言えば『ChatGPTはもの凄い』。

ChatGPT is awesome" regarding Python statistical library code, not just "ChatGPT lies.

-----

(Q1) np.random.randint(0, 5, GENOMS) の意味は?

(Q1) What does np.random.randint(0, 5, GENOMS) mean?

(Q2) pythonで1次元の行列を多次元にするには?

(Q2) How to make a one-dimensional matrix multidimensional in Python?

(Q3) pythonで1次元の行列を多次元する場合、行数だけ分かっている場合には?

(Q3) What if I want to make a one-dimensional matrix multidimensional in Python, and I only know the number of rows?

(Q4) 行列の要素を標準偏差値に変換するには?

(Q4) How do I convert matrix elements to standard deviation values?

(Q5) 算出した標準偏差値行列から固有値を計算するには?

(Q5) How do I calculate eigenvalues from the estimated standard deviation matrix?

(Q6) Pythonを使って算出した標準偏差値から因子分析を行うには?

(Q6) How can I perform a factor analysis from standard deviation values calculated using Python?

で、ChatGPTが提示したコードの『全て』が、動きました ―― いいですか。『全て』ですよ、『全て』。

So, "all" of the codes presented by ChatGPT worked -- OK? It is "All".

―― 今の私なら"ChatGPT教"に入信する

"I would join the ChatGPT cult now."

と、確信できるレベルです。

I am confident about it.

-----

では、このChatGPTを"神"のレベルに押し上げたのは誰か?

So, who has raised ChatGPT to the level of "God"?

もちろん、ChatGPTを制作されたOpenAIの皆さんであることは言うまでもありません。

It is the OpenAI people who produced ChatGPT.

しかし、その神を支えているのは、実は、私(たち)エンジニアなんです。

But It is engineers who support that God.

数多くのプログラムコードを、(著作権がどうのこうのと言うことなく)惜しげもなくネットに公開してきた、多くのエンジニアです。

Many engineers have generously released their program code online (without copyright concerns).

私が書いてきた『不快なコード』も ―― その貢献は、ほんとにささいなものかもしれませんが、役に立っているはずなのです。

The "uncomfortable" that I wrote -- its contribution may be trivial, but it must have been useful.

「作成プロセス途中の、小さくて、汚い、のソースコードを残して下さい」

そう考えると、痛快です。

That makes me happy.

-----

私の作った、汚い書き込みだらけのードは、今、第319世代の計算を終えて、私の当初目標の2倍近くの精度のデータ出力に成功しています。

My messy, write-filled Python code has now completed the 319th generation of calculations and is successfully outputting data with nearly twice the accuracy of my original goal.

あ、今、2倍を超えた。

Oh, now it's over twice as much.

"Generation: 328: Best fitness: 20.229819753125508. Worst fitness: 2.800005438880445"

高速化やら、スケールアップやら、課題は山積だけど、それは、これから考えればいいです。

Many issues must be addressed, such as increasing speed, scaling up, etc., but I will figure out that in the future.

先ずは、嬉しかったことを、ちゃんと喜ぼう。

First of all, let's feel happy about what makes me happy.

今からダイニングで、ノンアルビールで、一人で乾杯してきます。

I'm now off to the dining room to toast myself with a non-alcoholic beer.

2023,江端さんの忘備録

私が開示しているコードが「不快」と思われるのは、仕方がないです。

I can't help but if you think the code I am disclosing is "offensive."

―― 人のプログラムを読むことは、他人の人体を切り開いて、脳味噌や内蔵を覗きこむような不快感がある

私は「コードは動きさえすればいい」と思っていますし、コードの後片付けは敢えてしません。

I believe "code is good as long as it works," and I dare not clean up after code.

もっとも大切なことは、『後で私が思い出せること』だからです。

The most important thing is 'what I can remember later.'

「作成プロセス途中の、小さくて、汚い、のソースコードを残して下さい」

『過去の私と現在の私の間で行われる、共同開発』

-----

それでも、本当に稀ですが、私のコードを理解して動かそうとして、何週間もがんばってくれている人もいます。

Still, it is rare, but some people have been trying for weeks to understand my code and get it to work.

私も、そのような方の質問には、できるだけ答えするようにしています。

I try to answer questions from such people as much as possible.

私のコードを、ご自分の環境で無事動かした方には、『おめでとう & ありがとうメール』や、直接電話をして、祝辞を贈っています。

I congratulate those who have successfully run my code in their environment with a "Congratulations & Thank You Email" or by calling them directly.

ここ2年くらいで2人くらいしかいませんが(ちなみに、ソフト外注の皆さんは、仕事なので、この人数に含んでいません)。

However, there have only been about two of us in the last two years or so (by the way, this number does not include everyone at the software outsourcing company).

-----

比して ――

Compared to the above,

私が開示したコードに『不快』と言ってきた奴

You who said "offended" to me about the code I disclosed

私は、奴を絶対に許さない ―― 絶対に

I will never forgive you -- absolutely.

2023,江端さんの忘備録

どこかで犯罪が発生すると、ニュースで、その近所の人に対して、被疑者に関するインタビューが放送されます。

Whenever a crime occurs, the news broadcasts an interview about the suspect to the neighbors.

私は、この手のインタビューには絶対に応じませんし、家族にも応じないように言っています。

I would never respond to this interview and have told my family not to do it.

その映像が、『その後、どのように使われるか』分かったものではないからです。

We don't know how the images will be used afterward.

もし、被疑者にネガティブなコメントをした挙句、その事件が『20年後に再審で冤罪が確定判決』になろうものなら ―― そのインタビューに応じた人は『冤罪を誘発した人物』として、視聴者に記憶されることになります。

If a negative comment is made about a suspect and the case is "retried 20 years later, and the defendant is falsely convicted," - viewers will remember the interviewee as "the person who provoked the false conviction.

-----

最近、近所で『良い人』とされている人間による重大犯罪が報道されることが多いように思えますが ―― これ、恣意的な報道(偏向報道)の一例です。

Lately, there seem to be many reports of serious crimes committed by people considered 'good people' in the neighborhood -- this is an example of arbitrary reporting (biased reporting).

なぜか?

Why 'biased reporting'?

―― ご近所で、礼儀正しくて、大人しくて、目立たない人物による凶悪犯罪の方が、圧倒的に面白いから

"Because it is by far more interesting to make it a violent crime committed by a polite, quiet, inconspicuous person in your neighborhood."

です。

面白い方が、視聴率が稼げます。

The more interesting it is, the more ratings it will earn.

それ故『偏向報道』なのです。

Hence, it is 'biased reporting.

-----

私:「私が殺人事件を起こしたら、近所の人はインタビューに何と答えるかな?」

Me: "What would my neighbors say in an interview if I committed a murder?"

嫁さん:「『やっぱり・・・』、『いつかやると思っていたんですよ』、『挨拶もしないし、目付きも悪い人でした』、『町内会では、いつもトラブルメーカーでした』・・・」

Wife: "'I knew it...', 'I knew he was going to do it someday,' 'He never greeted me and had a bad eye,' 'He was always a troublemaker in the neighborhood association'..."

私:「もういい」

Me: "Enough."

―― 「遠山の金さん "冤罪"捕物帳」

2023,江端さんの忘備録

10年、100億円の費用をかけて、8割方開発が進んだ国家プロジェクトあったとします。

Suppose a national project took ten years and cost 10 billion yen, and 80% of the development had been completed.

―― その時、突如として、0.5億円(5000万円)程度の予算で、開発1ヶ月間で、現在のプロジェクトの3倍の効果が得られる新技術が登場する

Then, suddenly, a new technology appears that can triple the effectiveness of the current project with a budget of about 0.5 billion yen (50 million yen) and within one month of development

ということが、テクノロジーの世界では、結構な頻度で発生します。

This happens quite often in the world of technology.

『100億円、10年の日時と人材が、一瞬にゴミとなる』 ―― ここに、イノベーションの怖さがあります。

Ten billion yen, ten years, and human resources can be turned into garbage instantly" -- herein lies the fear of innovation.

(これは、あの"イノベーションのジレンマ"とは異なります)。

(This is different from the "innovation dilemma.)

しかも、そのようなイノベーションは、出現予測ができません。

Moreover, such innovations cannot be predicted to emerge.

ええ、もう、全然、予想できません。

Yeah, I can't predict it at all anymore.

例えば、昨年の今頃に『生成AIの出現と社会へのインパクト』を予想した人は、私が知る限り一人もいません。

For example, no one, as far as I know, predicted the 'emergence of generative AI and its impact on society' this time last year.

-----

規模や対象は全く異なるのですが、私にも似たようなことが起きます。

Something similar happens to me, although the scale and subject matter differ.

一週間、昼夜ぶっつづけで、ありとあらゆる方法をやりつくして『もうダメだ』という結論を纏めた報告書を書き終えた直後 ――

Just after I had finished writing a report that concluded that I had exhausted all possible methods, working day and night, and had come to the conclusion that "it was hopeless,"

『気紛れに試した方法で、課題が一瞬で解決してしまった』という目に会っています。

I am confronted with a situation where "a method I tried on a whim solved the problem instantly.

これは、もちろん技術者としては「幸せな話」なのですが、サラリーマンとしては「不幸な話」なのです。

This is, of course, a "happy story" for an engineer but an "unhappy story" for a businessman.

-----

イノベーションに社会が翻弄されるのは、仕方がないでしょう。

It is no wonder that society is at the mercy of innovation.

しかし、それ以上に、イノベーションのフロントに立っているエンジニアは、「仕方がない」などと言っていられないのです。

But more than that, the engineers on the front lines of the invention cannot say, "It cannot be helped."

正直なところ、

Honesty, I want to shout

―― 冗談じゃない!

"No kidding!"

と叫びたくなります。

―― うるさい!『イノベーションの作り方』なんぞどうでもいいから、お前の考えた『イノベーションそのもの』を教えろ!

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のトランスパイラはどれくらい速い?~