StackGP 0.0.13__tar.gz → 0.0.15__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: StackGP
3
- Version: 0.0.13
3
+ Version: 0.0.15
4
4
  Summary: A stack-based genetic programming system
5
5
  Author-email: Nathan Haut <hautnath@msu.edu>
6
6
  Project-URL: Homepage, https://github.com/hoolagans/StackGP
@@ -20,7 +20,10 @@ from sklearn.cluster import KMeans #for clustering in ensemble definition
20
20
  from scipy.optimize import minimize #for uncertainty maximization
21
21
  from sympy import symbols, simplify, expand
22
22
  import sympy as sym
23
- from IPython.display import display, clear_output
23
+ try:
24
+ from IPython.display import display, clear_output
25
+ except:
26
+ pass
24
27
 
25
28
  import signal #for timing out functions
26
29
  from contextlib import contextmanager #for timing out functions
@@ -50,6 +53,10 @@ def exp(a):
50
53
  # def sine(a,b):
51
54
  # return np.sin(a)
52
55
  def power(a,b):
56
+ if (type(a)==int or type(a)==float or type(a)==np.float64) and a==0:
57
+ return a/math.nan
58
+ if (type(a)==np.ndarray) and (0 in a):
59
+ return a/np.where(a==0,math.nan,a)
53
60
  return a**b
54
61
  def sqrt(a):
55
62
  return np.sqrt(a)
@@ -57,6 +64,8 @@ def sqrd(a):
57
64
  return a**2
58
65
  def inv(a):
59
66
  return np.array(a).astype(float)**(-1)
67
+ def neg(a):
68
+ return -a
60
69
  def sin(a):
61
70
  return np.sin(a)
62
71
  def cos(a):
@@ -73,6 +82,12 @@ def tanh(a):
73
82
  return np.tanh(a)
74
83
  def log(a):
75
84
  return np.log(a)
85
+ def log10(a):
86
+ return np.log10(a)
87
+ def log2(a):
88
+ return np.log2(a)
89
+ def abs1(a):
90
+ return np.abs(a)
76
91
 
77
92
  def and1(a,b):
78
93
  return np.logical_and(a,b)
@@ -91,9 +106,9 @@ def not1(a):
91
106
 
92
107
 
93
108
  def defaultOps():
94
- return [protectDiv,add,sub,mult,exp,sqrd,sqrt,inv,"pop","pop","pop","pop","pop","pop"]
109
+ return [protectDiv,add,sub,mult,exp,sqrd,sqrt,inv,neg,"pop","pop","pop","pop","pop","pop"]
95
110
  def allOps():
96
- return [protectDiv,add,sub,mult,exp,sqrd,sqrt,inv,cos,sin,tan,arccos,arcsin,arctan,tanh,log,"pop","pop","pop","pop","pop","pop","pop","pop","pop","pop"]
111
+ return [protectDiv,add,sub,mult,exp,sqrd,sqrt,inv,neg,cos,sin,tan,arccos,arcsin,arctan,tanh,log,"pop","pop","pop","pop","pop","pop","pop","pop","pop","pop"]
97
112
  def booleanOps():
98
113
  return [and1,or1,xor1,nand1,nor1,xnor1,not1,"pop","pop","pop","pop","pop","pop","pop"]
99
114
  def randomInt(a=-3,b=3):
@@ -109,7 +124,7 @@ def ranReal(a=20,b=-10):
109
124
  ############################
110
125
  #Data Subsampling Methods
111
126
  ############################
112
- def randomSubsample(x,y):
127
+ def randomSubsample(x,y, *args, **kwargs):
113
128
  n=max(int(np.ceil(len(y)**(3/5))),3)
114
129
  idx=np.random.choice(range(x.shape[1]),n,replace=False)
115
130
  return np.array([i[idx] for i in x]),y[idx]
@@ -119,6 +134,46 @@ def generationProportionalSample(x,y,generation=100,generations=100):
119
134
  idx=np.random.choice(range(x.shape[1]),n,replace=False)
120
135
  return np.array([i[idx] for i in x]),y[idx]
121
136
 
137
+ def ordinalSample(x,y,generation=100,generations=100):
138
+ n=max(int(len(y)*generation/generations),3)
139
+ sortedIdx=np.argsort(y)
140
+ step=len(y)/(n-1)
141
+ idx=[sortedIdx[max(int(i*step)-1,0)] for i in range(n)]
142
+ return np.array([i[idx] for i in x]),y[idx]
143
+
144
+ def orderedSample(x,y,generation=100,generations=100):
145
+ n=max(int(len(y)*generation/generations),3)
146
+ idx=[i for i in range(n)]
147
+ return np.array([i[idx] for i in x]),y[idx]
148
+
149
+ def ordinalBalancedSample(x,y,generation=100,generations=100):
150
+ n=max(int(len(y)*generation/generations),3)
151
+ numBins=int(max(np.ceil(np.sqrt(n)),3))
152
+ bins=np.linspace(min(y),max(y),numBins+1)
153
+ binIdx=np.digitize(y,bins)-1
154
+ samplesPerBin=max(int(n/numBins),1)
155
+ idx=[]
156
+ for i in range(numBins):
157
+ binMembers=[j for j in range(len(y)) if binIdx[j]==i]
158
+ if len(binMembers)>0:
159
+ chosen=np.random.choice(binMembers,min(samplesPerBin,len(binMembers)),replace=False)
160
+ idx=idx+chosen.tolist()
161
+ return np.array([i[idx] for i in x]),y[idx]
162
+
163
+ def balancedSample(x,y, *args, **kwargs):
164
+ n=int(np.ceil(len(y)**(3/5)))
165
+ numBins=max(n,3)
166
+ bins=np.linspace(min(y),max(y),numBins+1)
167
+ binIdx=np.digitize(y,bins)-1
168
+ samplesPerBin=max(int(n/numBins),1)
169
+ idx=[]
170
+ for i in range(numBins):
171
+ binMembers=[j for j in range(len(y)) if binIdx[j]==i]
172
+ if len(binMembers)>0:
173
+ chosen=np.random.choice(binMembers,min(samplesPerBin,len(binMembers)),replace=False)
174
+ idx=idx+chosen.tolist()
175
+ return np.array([i[idx] for i in x]),y[idx]
176
+
122
177
  import inspect
123
178
  def getArity(func): #Returns the arity of a function: used for model evaluations
124
179
  if func=="pop":
@@ -223,6 +278,8 @@ def evModHelper(varStack,opStack,tempStack,data): #Recursive helper function for
223
278
  evModHelper.__doc__ = "evModHelper(varStack,opStack,tempStack,data) is a helper function for evaluateGPModel"
224
279
  def rmse(model, inputData, response):
225
280
  predictions = evaluateGPModel(model, inputData)
281
+ if not all(np.isfinite(predictions)) or any(np.iscomplex(predictions)):
282
+ return np.nan
226
283
  return np.sqrt(np.mean((predictions - response) ** 2))
227
284
  rmse.__doc__ = "rmse(model, input, response) is a fitness objective that evaluates the root mean squared error"
228
285
  def binaryError(model, input, response):
@@ -667,7 +724,7 @@ def evolve(inputData, responseData, generations=100, ops=defaultOps(), const=def
667
724
  else:
668
725
  metrics=modelEvaluationMetrics
669
726
  if dataSubsample:
670
- inData,resData=samplingMethod(fullInput,fullResponse)
727
+ inData,resData=samplingMethod(fullInput,fullResponse,generations=generations,generation=i)
671
728
  for mods in models:
672
729
  setModelQuality(mods,inData,resData,modelEvaluationMetrics=metrics)
673
730
  models=removeIndeterminateModels(models)
@@ -766,7 +823,10 @@ def printGPModel(mod,inputData=symbols(["x"+str(i) for i in range(100)])): #Eval
766
823
  model[0] = replaceFunc(model[0],arctan,atan)
767
824
  model[0] = replaceFunc(model[0],tanh,tanh1)
768
825
  model[0] = replaceFunc(model[0],log,log2)
769
- response=evModHelper(model[1],model[0],[],np.array(inputData))[2][0]
826
+ try:
827
+ response=evModHelper(model[1],model[0],[],np.array(inputData))[2][0]
828
+ except:
829
+ return np.nan
770
830
  return response
771
831
 
772
832
  def ensembleSelect(models, inputData, responseData, numberOfClusters=10): #Generates a model ensemble using input data partitions
@@ -946,7 +1006,7 @@ def activeLearning(func, dims, ranges,rangesP,eqNum=1,version=1,iterations=100):
946
1006
  file.close()
947
1007
  return -1
948
1008
 
949
- def plotModels(models):
1009
+ def plotModels(models, modelExpression=False):
950
1010
  tMods=copy.deepcopy(models)
951
1011
  [modelToListForm(mod) for mod in tMods]
952
1012
  paretoModels=paretoTournament(tMods)
@@ -967,7 +1027,11 @@ def plotModels(models):
967
1027
  sc=plt.scatter(complexities,accuracies,color=colors)
968
1028
  plt.xlabel("Complexity")
969
1029
  plt.ylabel("1-R**2")
970
- names=[str(printGPModel(mod)) for mod in tMods]+[str(printGPModel(mod)) for mod in paretoModels]
1030
+
1031
+ if modelExpression:
1032
+ names=[str(printGPModel(mod)) for mod in tMods]+[str(printGPModel(mod)) for mod in paretoModels]
1033
+ else:
1034
+ names = [str(mod) for mod in tMods]+[str(mod) for mod in paretoModels]
971
1035
 
972
1036
  label = ax.annotate("", xy=(0,0), xytext=(np.min(complexities),np.mean([np.max(accuracies),np.min(accuracies)])),
973
1037
  bbox=dict(boxstyle="round", fc="w"),
@@ -1171,3 +1235,25 @@ def runEpochs(x,y,epochs=5,**kwargs):
1171
1235
  models+=evolve(x,y,**kwargs)
1172
1236
 
1173
1237
  return sortModels(models)
1238
+
1239
+
1240
+ ############################
1241
+ #Benchmarking
1242
+ ############################
1243
+ def generateRandomBenchmark(numVars=5, numSamples=100, noiseLevel=0, opsChoices=defaultOps(), constChoices=defaultConst(), maxLength=10):
1244
+
1245
+ # Generate random input data
1246
+ inputData = np.random.rand(numVars, numSamples)
1247
+
1248
+ # Generate a random target function
1249
+ randomModel = generateRandomModel(numVars, opsChoices, constChoices, maxLength)
1250
+
1251
+ # Evaluate the model to get response data
1252
+ responseData = evaluateGPModel(randomModel, inputData)
1253
+
1254
+ # Add noise if specified
1255
+ if noiseLevel > 0:
1256
+ noise = np.random.normal(0, noiseLevel, size=responseData.shape)
1257
+ responseData += noise
1258
+
1259
+ return inputData, responseData, randomModel
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: StackGP
3
- Version: 0.0.13
3
+ Version: 0.0.15
4
4
  Summary: A stack-based genetic programming system
5
5
  Author-email: Nathan Haut <hautnath@msu.edu>
6
6
  Project-URL: Homepage, https://github.com/hoolagans/StackGP
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "StackGP"
3
- version = "0.0.13"
3
+ version = "0.0.15"
4
4
  authors = [
5
5
  { name="Nathan Haut", email="hautnath@msu.edu" },
6
6
  ]
File without changes
File without changes
File without changes
File without changes