I'm pretty new to Python so I'm sure this isn't the most efficient way to code this. The problem I'm having is I have a 2nd For loop that runs inside another for loop. It works fine the first time, but on the second iteration, the second for loop doesn't register the data and skips over it so the it never runs again. I use a zipped tuple and it just looks like it loses the value completely. `
class Model:
def predict(self, data):
prediction = []
distances = []
for item in data:
distances.clear()
for trainedItem in self.Train_Data:
distances.append([(abs((item[0] - trainedItem[0][3])) + abs((item[1] - trainedItem[0][1])) + abs((item[2] - trainedItem[0][2])) + abs((item[3] - trainedItem[0][3]))), trainedItem[1]])
distances.sort()
targetNeighbors = []
for closest in distances[:self.K]:
targetNeighbors.append(closest[1])
prediction.append(Counter(targetNeighbors).most_common()[0][0])
return prediction
class HardcodedClassifier:
def fit(X_Train, Y_Train, k):
Model.Train_Data = zip(X_Train, Y_Train)
Model.K = k
return Model`
The iterator was depleted. Try Model.Train_Data = list(zip(X_Train, Y_Train)) so it will iterate every time in the inner for loop.
Based on what I see, you are calling the Model class constructor instead of instantiating a model object and accessing its data. When you declare a class, the declaration only creates a constructor object. The constructor returns a new object of the type you defined when called.
class Bacon:
tasty = true
def __init__():
self.salty = true
Bacon
>> <class constructor object at #memoryaddress>
Bacon.tasty
>> True
Bacon.salty
>> Error: Attribute not found
baconstrip = Bacon()
baconstrip
>> <Bacon object at #memoryaddress>
baconstrip.tasty
>> True
baconstrip.salty
>> True
The baconstrip object is of type Bacon and has memory and its own namespace allocated to it to store variables. The Bacon variable is the constructor, and you can also access it like an object too, but it's not an actual instance of itself.
For your code:
class HardcodedClassifier:
def __init__(self, model): # to initialize the class, provide a model.
self.model = model
def fit(X_Train, Y_Train, k):
self.model.Train_Data = zip(X_Train, Y_Train)
self.model.K = k
# no need to return a value. The state of the object is preserved.
mymodel = Model()
myclassifier = HardcodedClassifier(mymodel)
Related
My problem is quite simple but I am unable to solve it. When I insert objects into a list, the elements of the list all change whenever I change one of them (they all point to the same object in the memory I think). I want to unlink them so the list would not be full of the exactly same objects with the same values. E.g. avoid linking or mutability. I think the problem is how I initialize the objects but I am not sure how to solve it. Here is my code.
from typing import List, Tuple
class State:
#think of State as some kind of coordinates
def __init__(self, z:float, angle:float):
self.z = z
self.angle = angle
class ListOfStates:
#this should be an object with a list containing DIFFERENT (unlinked) State objects
def __init__(self, list_of_states : List[State]):
self.list_of_states = list_of_states
class StateSettings:
#a bigger object to encapsulate previous objects
def __init__(self, state : State, list_of_states : ListOfStates):
self.state = state
self.list_of_states = list_of_states
some_number = 42
# my try #1
state_settings = StateSettings
#create a list of State objects to be used later
state_settings.list_of_states = [State for i in range(some_number)]
state_settings.state = State
for i in range(some_number):
state_settings.list_of_states[i].angle = i
And state_settings.list_of_states contains the same copy of the object 42 times, e.g.
print(state_settings.list_of_states[0].angle)
print(state_settings.list_of_states[1].angle)
print(state_settings.list_of_states[2].angle)
prints
41
41
41
I also tried different ways to initialize, but with no luck.
# my try #2
state_settings = StateSettings(
state = State(
z = 0,
angle = 0),
list_of_states = [State for i in range(some_number)]
)
for i in range(some_number):
state_settings.list_of_states[i].angle = i
or
# my try 3
from copy import deepcopy
state_settings = StateSettings
state_settings.list_of_states = [deepcopy(State) for i in range(some_number)]
state_settings.state = deepcopy(State)
for i in range(some_number):
state_settings.list_of_states[i].angle = i
My question, as far as I know, is not solved by answers such as Changing a single object within an array of objects changes all, even in a different array or List of Objects changes when the object that was input in the append() function changes.
There are some fundamental mistakes you have made in the code. Let me try to put some light on those first , using your lines of code
# my try #1
state_settings = StateSettings
What you did in the above line is that, you assigned the class StateSettings to state_settings variable. You never created an object here.
#create a list of State objects to be used later
state_settings.list_of_states = [State for i in range(some_number)]
What you did here is also same, created a list of State class references, not objects. So, all the values in list are same.
state_settings.state = State
What you did here, is set an attribute state to StateSettings class , not the object.
for i in range(some_number):
state_settings.list_of_states[i].angle = i
What you did here, set an attribute angle the class State. Since all values in the list are same State references, everywhere value will be same
To summarize the above said issues,
When you assign an attribute to the class name, attribute gets added to the class itself. Any where you have a reference to that class will have the same attribute value.
When you create an object and then set an attribute on the object, the attribute lies only in that object. Its not reflected on other objects created.
A simple update on the code you wrote is below, which I guess works like you want.
from typing import List
class State:
# think of State as some kind of coordinates
# Use default values, so you dont need to provide a value in init
def __init__(self, z: float = None, angle: float = None):
self.z = z
self.angle = angle
class ListOfStates:
# this should be an object with a list containing DIFFERENT (unlinked) State objects
# Use default values, so you dont need to provide a value in init
def __init__(self, list_of_states: List[State] = None):
self.list_of_states = list_of_states
class StateSettings:
# a bigger object to encapsulate previous objects
# Use default values, so you dont need to provide a value in init
def __init__(self, state: State = None, list_of_states: ListOfStates = None):
self.state = state
self.list_of_states = list_of_states
some_number = 42
# my try #1
state_settings = StateSettings()
# create a list of State objects to be used later
state_settings.list_of_states = [State() for i in range(some_number)]
state_settings.state = State()
for i in range(some_number):
state_settings.list_of_states[i].angle = i
I have a recommender system that I need to train, and I included the entire training procedure inside a function:
def train_model(data):
model = Recommender()
Recommender.train(data)
pred = Recommender.predict(data)
return pred
something like this. Now if I want to train this inside a loop, for different datasets, like:
preds_list = []
data_list = [dataset1, dataset2, dataset3...]
for data_subset in data_list:
preds = train_model(data_subset)
preds_list += [preds]
How can I make sure that every time I call the train_model function, a brand new instance of a recommender is created, not an old one, trained on the previous dataset?
You are already creating a new instance everytime you execute train_model. The thing you are not using the new instance.
You probably meant:
def train_model(data):
model = Recommender()
model.train(data)
pred = model.predict(data)
return pred
Use the instance you've instantiated, not the class
class Recommender:
def __init__(self):
self.id = self
def train(self, data):
return data
def predict(self, data):
return data + str(self.id)
def train_model(data):
model = Recommender()
model.train(data)
return model.predict(data)
data = 'a data '
x = {}
for i in range(3):
x[i] = train_model(data)
print(x[i])
# a data <__main__.Recommender object at 0x11cefcd10>
# a data <__main__.Recommender object at 0x11e0471d0>
# a data <__main__.Recommender object at 0x11a064d50>
I have a simple class that stores simple data. The class is as follows.
class DataFormater:
def __init__(self, N, P, K, price):
self.N = N
self.P = P
self.K = K
self.price = price
The code that calls this class is
from DataFormater import DataFormater
#global variables
ObjectList = [0,1,2,3,4,5,6,7,8,9,10,
11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,
31,32,33,34,35,36,37,38,39,40,
41,42,43,44,45,46,47,48,49,50]
ObjectListCounter = 0
# main
print "enter you N-P-K values, followed by a coma, then the price"
print "example ----> 5 5 5 %50 "
print "return as many values as you want to sort, then enter, 'done!' when done."
while True:
RawData = raw_input()
if RawData == 'done!':
break
else:
ObjectList[ObjectListCounter] = DataFormater
ObjectList[ObjectListCounter].N = int(RawData[0])
# very simple test way of putting first indice in ObjectList[ObjectListCounter].N
ObjectListCounter += 1
print ObjectList[0].N
print ObjectList[1].N
My idea is that ObjectList[0] would create that object '1' that I could call with 1.N
But, when I call these, it seems that I have overwritten the previous instances.
this is what prints...
return as many values as you want to sort, then enter, 'done!' when done.
12
1
done!
1
1
Thanks so much! And I know that my post is messy, I don't exactly know how to make it more "pretty"
So, it looks like you are assigning the actual class (instead of an instance of the class) in your loop. Where you do this:
ObjectList[ObjectListCounter] = DataFormater
I think what you actually want is this
ObjectList[ObjectListCounter] = DataFormater(...insert args here....)
EDIT to address the comments:
Your class init method looks like this:
def __init__(self, N, P, K, price):
That means that to create an instance of your class, it would look like this:
my_formater = DataFormater(1, 2, 3, 4)
You would then be able to access my_formater.N which would have a value of 1.
What you are trying to do instead is access a CLASS level attribute, DataFormater.N. This is generally used in situations where you have a constant variable that does not change between instances of the class. For example:
class DataFormater():
CONSTANT_THING = 'my thing that is always the same for every instance'
You would then be able to access that variable directly from the class, like this:
DataFormater.CONSTANT_THING
I hope that clears things up.
I want to define a class and then make a dynamic number of copies of that class.
Right now, I have this:
class xyz(object):
def __init__(self):
self.model_type = ensemble.RandomForestClassifier()
self.model_types = {}
self.model = {}
for x in range(0,5):
self.model_types[x] = self.model_type
def fit_model():
for x in range(0,5):
self.model[x] = self.model_types[x].fit(data[x])
def score_model():
for x in range(0,5):
self.pred[x] = self.model[x].predict(data[x])
I want to fit 5 different models but I think Python is pointing to the same class 5 times rather than creating 5 different classes in the model dictionary.
This means that when I use the "score_model" method, it is just scoring the LAST model that was fit rather than 5 unique models.
I think that I just need to use inheritance to populate the model[] dictionary with 5 distinct classes but I'm not sure how to do that?
In your orignal code, you created one instance and used it five times. Instead, you want to initialize the class only when you add it to the model_types array, as in this code.
class xyz(object):
def __init__(self):
self.model_type = ensemble.RandomForestClassifier
self.model_types = {}
self.model = {}
for x in range(0,5):
self.model_types[x] = self.model_type()
def fit_model():
for x in range(0,5):
self.model[x] = self.model_types[x].fit(data[x])
def score_model():
for x in range(0,5):
self.pred[x] = self.model[x].predict(data[x])
In python everything is an object, so your variable can point to a class as well, and then your variable can be treated as a class.
I'm trying to implement trie in python. I'm using dictionaries+classes instead of lists (I know it's not optimal, but I'm just trying to make it work at all).
After debugging I found out that each layer has all letters in dictionary. I cannot understand why.
Here is my code (implementation is 100% most basic, straightforward):
class lttr:
finish = 0
pointers = {} #for letters to reference class instance
eps = lttr()
def add(word):
global eps
last = eps
for ind,x in enumerate(word):
if last.pointers.get(x,None):
last = last.pointers[x]
else:
last.pointers[x] = lttr()
last=last.pointers[x]
last.finish=1
def lookup(word):
global eps
last=eps
for ind,x in enumerate(word):
if last.pointers.get(x,None):
last=last.pointers[x]
else:
return False
return bool(last.finish)
add("pear")
print lookup("ar") #prints True ... but why?
I'm guessing you intended for each individual lttr instance to have its own unique values for finish and pointers. In which case, you need to declare them as attributes of self inside __init__, rather than just defining them at the class scope.
class lttr:
def __init__(self):
self.finish = 0
self.pointers = {} #for letters to reference class instance
Now your script will print False as expected.
Your lttr class has class variables, but you want instance variables. Class variables are unique across all instances of that class, so you only have one pointers object.
class lttr:
finish = 0
pointers = {} #for letters to reference class instance
What you want is
class lttr:
def __init__(self):
self.finish = 0
self.pointers = {}
and that works as expected.