CSVファイルが無いので未検証。実行して確かめて下さい
【変更すべきポイント】
1.データ読込み
男性データと女性データを扱うため、CSV の性別列を使ってフィルタ処理を変更する必要がある。
「rows = [row for row in reader ・・・]」
2.モデル関数の定義
現在は、直線
「ax + b」 を使っているが、
これをロジスティック関数
「L / (1 + exp(-k(x - x0)))」
に置き換える必要がある。
3.パラメータの初期値
直線回帰では
[0, 0] だが、
ロジスティック関数では
[L, k, x0]
のように三つの初期値を設定する必要がある。
4.残差関数の定義
ロジスティック関数に合わせて、model_func の呼び出しとパラメータ数を変更する必要がある。
5.最小二乗法の実行
optimize.leastsq はそのまま使えるが、パラメータ数が増えるため、初期値と返り値の扱いを変更する必要がある。
6.プロット部分
回帰直線を描画している部分を、ロジスティック曲線の描画に変更する必要がある。
ラベル名もロジスティック曲線に合わせて変更
以下の感じになると思う。
~~ [参考] ~~
import csv
import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt
csv_file = 'b-29-height-male.csv' # 性別情報も含むCSVと仮定
# データ読み込み(性別で分離)
with open(csv_file, 'r', encoding='utf-8') as f:
reader = csv.reader(f)
rows = [row for row in reader if row] # 空行除去
# 男女データ(例:row[2]が性別とする)
male_data = [row for row in rows if row[2] == 'male']
female_data = [row for row in rows if row[2] == 'female']
# numpy配列に変換
male_data = np.float_(np.array([[row[0], row[1]] for row in male_data]))
female_data = np.float_(np.array([[row[0], row[1]] for row in female_data]))
# ロジスティック関数定義
def logistic_func(L, k, x0, x):
return L / (1 + np.exp(-k * (x - x0)))
def fit_func(par, x, y):
L, k, x0 = par
y_model = logistic_func(L, k, x0, x)
return y_model - y
# フィッティング関数
def fit_and_plot(data, label):
x = data[:, 0]
y = data[:, 1]
par_init = [max(y), 0.1, np.mean(x)]
result = optimize.leastsq(fit_func, par_init, args=(x, y))
L, k, x0 = result[0]
print(f\u0026quot;{label} パラメータ: L={L:.2f}, k={k:.2f}, x0={x0:.2f}\u0026quot;)
plt.plot(x, y, 'o', label=f'{label} 実データ')
plt.plot(x, logistic_func(L, k, x0, x), '-', label=f'{label} ロジスティック曲線')
# 描画
plt.figure()
fit_and_plot(male_data, '男性')
fit_and_plot(female_data, '女性')
plt.xlabel('身長(cm)')
plt.ylabel('体重(kg)')
plt.legend()
plt.grid(True)
plt.show()
━