質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1991閲覧

python ユークリッド距離で近似誤差のグラフを出力する。(2)

tiroha

総合スコア109

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2020/11/10 05:55

編集2020/11/11 01:20

ユークリッド距離を使って、フ―リエ展開した関数と元の関数の近似誤差のグラフを出力するプログラムを完成させたいです。
fse103.pyのようなグラフが出力されると成功なのですが、上手くいきません。
出力をすると、誤差が指数関数的に増えていくというありえないグラフになります。
def diff(K)内のs=の式を変えてみたりしたのですが、上手くいきませんでした。
func(t,k)の関数は他のプログラムでグラフとして出力できているので、問題があるとしたら、def diff(K)です。
上手くいかないプログラムはfa104.pyです。
どなたか詳しい方、ご指摘をお願いします。
~追記~
fa104.pyの元の関数はf(t)= 1 (-π <= t < 0) かつ 0 (0 <= t <π)とtを関数上に記述しないので、どうプログラムで表現すればいいか悩んでいます。

python

1#fse103.py 2# -*- coding: utf-8 -*- 3import numpy as np 4import matplotlib.pyplot as plt 5 6def func(t,k): 7 return 2.0*np.power(-1.0,k+1)*np.sin(k*t)/k 8 9def diff(K): 10 dt = 0.01 11 start = -1.0*np.pi 12 end = 1.0*np.pi 13 t = np.arange(start, end, dt) 14 s = 0*t 15 for k in range(1,K): 16 s = s + func(t,k) 17 return np.linalg.norm(s-t, ord=2) 18 19# maxK = np.arange(-np.pi, np.pi, 0.01).size 20maxK = 100 21K = np.arange(1,maxK, 1) 22r = [] 23for k in range(1,maxK): 24 r.append( diff(k) ) 25 26fig=plt.figure(0) 27plt.plot (K, r, linewidth=1.0, color="r",linestyle="solid",label="$ f(t)=t $") 28plt.xlabel("$K$-th approximation", fontsize=14, color="black") 29plt.ylabel("error", fontsize=14) 30plt.grid() 31plt.legend() 32plt.show() 33fig.savefig('fig323.pdf') 34

python

1#fa104.py 2# -*- coding: utf-8 -*- 3import numpy as np 4import matplotlib.pyplot as plt 5 6def func(t,k): 7 return 2.0*np.sin((2.0*k-1.0)*t)/(2.0*k-1.0)*np.pi 8 9def diff(K): 10 dt = 0.01 11 start = -1.0*np.pi 12 end = 1.0*np.pi 13 t = np.arange(start, end, dt) 14 s = 0*t 15 for k in range(1,K): 16 s = s + func(t,k) 17 return np.linalg.norm(s-t, ord=2) 18 19# maxK = np.arange(-np.pi, np.pi, 0.01).size 20maxK = 100 21K = np.arange(1,maxK, 1) 22r = [] 23for k in range(1,maxK): 24 r.append( diff(k) ) 25 26fig=plt.figure(0) 27plt.plot (K, r, linewidth=1.0, color="r",linestyle="solid",label="$ f(t)=t $") 28plt.xlabel("$K$-th approximation", fontsize=14, color="black") 29plt.ylabel("error", fontsize=14) 30plt.grid() 31plt.legend() 32plt.show() 33fig.savefig('fig323.pdf') 34

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

toast-uz

2020/11/10 13:50 編集

diff(K)は、f(t) = s = func(1, t) + func(2, t) + func(3,t) +・・・と、g(t)=t の差分を求めるものになっています。return np.linalg.norm(s-t, ord=2) が差分のL2-normを求めている部分です。 すなわち、コードとしては、f(t)がフ―リエ展開した関数、g(t)=tが元の関数、ということを表していますが、認識はあっていますでしょうか?おそらくg(t)が認識と違うのでは、と思います。
tiroha

2020/11/11 01:18

回答ありがとうございます! なるほど。fa104.pyの元の関数はf(t)= 1 (-π <= t < 0) かつ 0 (0 <= t <π)とtを関数上に記述しないので、どうプログラムで表現するか悩んでいました。
guest

回答1

0

ベストアンサー

質問者様のコードでは、差分計算のための元の関数がt→tという恒等関数になっており、かつ差分ノルム計算関数diffの中に埋め込まれています。変換前後の差分計算をするためには、元の関数も対応して修正する必要があります。

元の関数、変換後の関数(K項まで展開)、差分ノルム計算、を区別して、質問者様のコード前半を、以下のように実装すると、修正忘れが無くなると思います。関数の中身は、本来比較したいものに修正ください。なお、こういったnumpy配列を入力とする関数を作る際には、np.vectorizeを使うと便利です。

Python

1# 変換元関数 2def func_f(t): 3 def func_f_element(t): 4 if -np.pi <= t < 0: 5 return 1 # func_f(t) = t 6 if 0 <= t < np.pi: 7 return 0 8 f = np.vectorize(func_f_element) 9 return f(t) 10 11# 変換先関数 K項まで展開 12def func_g(t, K): 13 def func_g_k(t,k): 14 return 2.0*np.power(-1.0,k+1)*np.sin(k*t)/k 15 s = 0*t 16 for k in range(1,K): 17 s = s + func_g_k(t,k) 18 return s 19 20def diff(K): 21 dt = 0.01 22 start = -1.0*np.pi 23 end = 1.0*np.pi 24 t = np.arange(start, end, dt) 25 return np.linalg.norm(func_g(t, K)-func_f(t), ord=2)

投稿2020/11/11 03:47

編集2020/11/11 14:43
toast-uz

総合スコア3266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tiroha

2020/11/11 04:57

回答ありがとうございます。 さっそく書き加えて、組み込んでみたのですが、コンパイルが通りませんでした。 エラー内容は Traceback (most recent call last): File "fa104.py", line 50, in <module> r.append( diff(k) ) File "fa104.py", line 43, in diff return np.linalg.norm(func_g(t, K)-func_f(t), ord=2) File "fa104.py", line 23, in func_f if -np.pi <= t < 0: ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() とでます。if文の確認は何度もしましたが、どこが間違いなのかよくわかりませんでした。 a.anyは真理判定なので必要ないと思いますがどうでしょうか?
tiroha

2020/11/11 04:58

```python # -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt # 変換元関数 def func_f(t): if -np.pi <= t < 0: return 1 # func_f(t) = t if 0 <= t < np.pi: return 0 # 変換先関数 K項まで展開 def func_g(t, K): def func_g_k(t,k): return 2.0*np.sin((2.0*k-1.0)*t)/(2.0*k-1.0)*np.pi s = 0*t for k in range(1,K): s = s + func_g_k(t,k) return s # 差分ノルム計算 def diff(K): dt = 0.01 start = -1.0*np.pi end = 1.0*np.pi t = np.arange(start, end, dt) return np.linalg.norm(func_g(t, K)-func_f(t), ord=2) # maxK = np.arange(-np.pi, np.pi, 0.01).size maxK = 100 K = np.arange(1,maxK, 1) r = [] for k in range(1,maxK): r.append( diff(k) ) fig=plt.figure(0) plt.plot (K, r, linewidth=1.0, color="r",linestyle="solid",label="$ f(t)=t $") plt.xlabel("$K$-th approximation", fontsize=14, color="black") plt.ylabel("error", fontsize=14) plt.grid() plt.legend() plt.show() fig.savefig('fig323.pdf') ```
toast-uz

2020/11/11 10:53 編集

tはnumpy配列ですので、普通の感覚で計算はできません。マイナスで1、プラスで0の関数を作りたいのであれば以下のようにします。 def func_f(t): return (t < 0).astype(int) # t<0なら1, t>=0なら0 また上記のような記述がパッと浮かばなければ、普通の関数を「numpyベクトル化」するvectorizeというものがあり、こちらを使うとよいでしょう。インデントが表せないため、わかりにくいかもですが、元の関数をfunc_f_elementとして内側に書き、vectorizeした関数fを仲介して値を返します。 def func_f(t): def func_f_element(t): if -np.pi <= t < 0: return 1 # func_f(t) = t if 0 <= t < np.pi: return 0 f = np.vectorize(func_f_element) return f(t)
tiroha

2020/11/11 13:40

回答ありがとうございます。 なるほど。ベクトルと普通の数字を比較できないわけですね。 上の記述はピンとこなかったので、下の記述を参考にさせていただきます。 # -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt def func_f(t): def func_f_element(t): if -np.pi <= t < 0: return 1 # func_f(t) = t if 0 <= t < np.pi: return 0 f = np.vectorize(func_f_element) return f(t) # 変換先関数 K項まで展開 def func_g(t, K): def func_g_k(t,k): return 2.0*np.sin((2.0*k-1.0)*t)/(2.0*k-1.0)*np.pi s = 0*t for k in range(1,K): s = s + func_g_k(t,k) return s # 差分ノルム計算 def diff(K): dt = 0.01 start = -1.0*np.pi end = 1.0*np.pi t = np.arange(start, end, dt) return np.linalg.norm(func_g(t, K)-func_f(t), ord=2) # maxK = np.arange(-np.pi, np.pi, 0.01).size maxK = 100 K = np.arange(1,maxK, 1) r = [] for k in range(1,maxK): r.append( diff(k) ) fig=plt.figure(0) plt.plot (K, r, linewidth=1.0, color="r",linestyle="solid",label="$ f(t)=t $") plt.xlabel("$K$-th approximation", fontsize=14, color="black") plt.ylabel("error", fontsize=14) plt.grid() plt.legend() plt.show() fig.savefig('fig323.pdf') def func_f(t)内の最後のreturnはreturn fではないんですか? また、これをコンパイルすると File "fa104.py", line 36, in <module> r.append( diff(k) ) File "fa104.py", line 29, in diff return np.linalg.norm(func_g(t, K)-func_f(t), ord=2) TypeError: unsupported operand type(s) for -: 'float' and 'NoneType' と出てきて、型が違うもの同士を計算しようとしていて、エラーが出てきます。 型は特に指定していないので、同じだと考えていましたが、違いますか?型の違うものを計算するにはどうすれば良いでしょうか?
toast-uz

2020/11/11 14:47

私の方ではうまく動いていますので、おそらくfunc_f(t)の関数のどこかで、インデントが違うのではと思います。最新の回答を貼っておきましたので、確認ください。なおreturn f(t)はこれで正しいです。この場合、fはnumpy配列→numpy配列の関数です。それに実際のnumpy配列t (x軸に相当)を入れることで、結果のnumpy配列(yの値に相当)を求める必要があります。比較対象のgも同様の形式ですので。
tiroha

2020/11/12 00:27

回答ありがとうございます。 ご指摘の通り、func_f(t)関数内のインデントが違っていたようです。 エラーが出なくなりました。しかし、グラフを出力すると近似誤差がどんどん大きくなっていきます。 理想としては0に近付くようなグラフを出力したいです。 ノルム計算が違うのかと思って、 return np.linalg.norm(func_f(t)-func_g(t, K), ord=2) と書き換えても同じ結果が出力されます。
toast-uz

2020/11/12 03:42 編集

> グラフを出力すると近似誤差がどんどん大きくなっていきます 実際にfとgはかけ離れていますので、結果は当然です。もはやコードの問題ではなく、数学の問題です。展開ができていません。
tiroha

2020/11/12 05:27

回答ありがとうございます。再計算したら、展開した式が違いました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問