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

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

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

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

解決済

木構造で数式を表す際、指数関数と多項式の合成関数を作りたいです。

AI_engineer
AI_engineer

総合スコア10

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

2回答

0リアクション

0クリップ

253閲覧

投稿2022/07/14 04:00

編集2022/07/14 06:15

前提

pythonで木構造を用いて数式を生成するコードを書いています。その際、指数関数と多項式の合成関数をどのように生成すればよいか思いつかないのでアドバイスをいただきたいです。

実現したいこと

木構造を使って、
(ex1) x^2 + 2 * (x+1) * exp(x)
などという数式を生成することはできたのですが、
(ex2) x^2 + 2 * (x+1) * exp(x^2+1)
の太字の部分のように指数関数exp(x)のx部分に多項式が来るような数式を生成できるようにしたいです。

該当のソースコード

python

import numpy as np from random import random, randint, seed def add(x, y): return x + y def sub(x, y): return x - y def mul(x, y): return x * y def div(x, y): return 1 if y == 0 else x / y FUNCTIONS = [add, sub, mul, div] # 木構造の非終端ノード(四則演算) TERMINALS = ['x', 'exp', -2, -1, 0, 1, 2] # 木構造の終端ノード(定数or入力変数x or exp(x)) class GPTree: def __init__(self, data = None, left = None, right = None): self.data = data self.left = left self.right = right def node_label(self): if (self.data in FUNCTIONS): return self.data.__name__ else: return str(self.data) def random_tree(self, grow, max_depth, depth = 0): # 木構造(数式)を生成 if depth < 2 or (depth < max_depth and not grow): self.data = FUNCTIONS[randint(0, len(FUNCTIONS)-1)] elif depth >= max_depth: self.data = TERMINALS[randint(0, len(TERMINALS)-1)] else: # intermediate depth, grow if random () > 0.5: self.data = TERMINALS[randint(0, len(TERMINALS)-1)] else: self.data = FUNCTIONS[randint(0, len(FUNCTIONS)-1)] # 右と左の木を生成 if self.data in FUNCTIONS: self.left = GPTree() self.left.random_tree(grow, max_depth, depth = depth + 1) self.right = GPTree() self.right.random_tree(grow, max_depth, depth = depth + 1) # 数式を生成する関数(x:入力変数) def compute_tree(self, x): if (self.data in FUNCTIONS): return self.data(self.left.compute_tree(x), self.right.compute_tree(x)) elif self.data == 'x': return x elif self.data == 'exp': return np.exp(x) else: return self.data def print_tree(self, prefix = ""): # 生成した木構造を出力する関数 print("%s%s" % (prefix, self.node_label())) if self.left: self.left.print_tree (prefix + " ") if self.right: self.right.print_tree(prefix + " ") t = GPTree() t.random_tree(grow=True, max_depth=5) t.print_tree()

コードの補足説明

random_treeメソッド
木構造を初期化しています。grow変数の真偽によって処理を分岐していますが、実現したいこととはあまり関係がないので今は無視していただいて構いません。

compute_treeメソッド
木構造から数式を生成する関数です。ここのexpの処理を変えるべきだと思っています。
現段階ではexp(x)をそのままreturnするとなっているため、最終的に生成される数式で指数関数と多項式の合成形を作れないのだろうと考えています。ですが、実装力の問題でどのようにコードを書けばよいか思い浮かばず困っています。

修正後のコード

expを終端記号から非終端記号に変更するとよいとのアドバイスをいただいたので、自分なりにコードを修正してみました。

python

# exp()を非終端記号に変更 def add(x, y): return x + y def sub(x, y): return x - y def mul(x, y): return x * y def div(x, y): return 1 if y == 0 else x / y def exp(x): return np.exp(x) FUNCTIONS = [add, sub, mul, div, exp] TERMINALS = ['x', -2, -1, 0, 1, 2] # exp(x)の子ノードの部分木をxに代入するように変更 def random_tree(self, grow, max_depth, depth = 0): # create random tree using either grow or full method """初期集団の生成 Args: grow (_type_): FUNCTIONから選ぶかを操作 max_depth (_type_): 木の深さの上限 depth (int, optional): 現在の木の深さ. Defaults to 0. """ if depth < MIN_DEPTH or (depth < max_depth and not grow): self.data = FUNCTIONS[randint(0, len(FUNCTIONS)-1)] elif depth >= max_depth: self.data = TERMINALS[randint(0, len(TERMINALS)-1)] else: # intermediate depth, grow # grow=True且つdepth < max_depth if random () > 0.5: self.data = TERMINALS[randint(0, len(TERMINALS)-1)] else: self.data = FUNCTIONS[randint(0, len(FUNCTIONS)-1)] # 右と左の木を生成 if self.data == exp: self.left = GPTree() self.left.random_tree(grow, max_depth, depth = depth + 1) elif self.data in FUNCTIONS: self.left = GPTree() self.left.random_tree(grow, max_depth, depth = depth + 1) # 木の深さを更新 self.right = GPTree() self.right.random_tree(grow, max_depth, depth = depth + 1)

これを実行すると、

RuntimeWarning: overflow encountered in exp
def exp(x): return np.exp(x)
a.py:156: RuntimeWarning: overflow encountered in double_scalars
return sum([((individual.compute_tree(ds[0])np.sqrt(2np.pi)) - ds[1]) ** 2 for ds in dataset])

などのエラーがでてしまい、解決方法がわからず困っています。
エラー文について調べて、指数関数expは膨大な値になるためオーバーフローしたのだと考えていますが、改善の仕方がわかりません...

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。