Dataquest missions
机器学习评估指标——分类
- Accuracy
- Precisionfpr 预测为正的样本中有多少是真正的正样本P = TP/(TP+FP)
- Recall tpr 样本中的正例有多少被预测正确了,包含两种一个是正确的预测正例,一个是错误预测成了负例R = TP/(TP+FN)
- F1Score
- ROCCurve
- PRCurve
- AUC
| Positive | Negative |
1 | TP | TN |
0 | FP | FN |
-
数据结构
数据结构是组织数据的形式,如列表Lists和字典dictionaries等。
- 数据结构的选择要素:首先是我们如何存储的,第二是插入删除和查找的时间复杂度。
- Array:一个包含item的list
- 很多语言都有一个内置的原始数组形式,但是python不具有原始的固定长度的数组,但是python的list时一个动态数组
- 动态数组是数组的一种风格,我们可以扩展以适应尽可能多的元素。这些在数据科学中比固定大小的数组更有用
• 一个长的存储空间链(along chain of memory slots):每个元素依次保存在存储空间中
• 当删除或增加元素时,所有的元素都需要依次的移动,导致该类操作非常耗时
• 无法扩展初始定义的长度,如果是个10个元素的array,则不会改变
players.insert(0, "Jeff Adrien")
print(players)
players.remove("Reggie Jackson")
print(players)
- 2D数组:矩阵遍历复杂度O(m*n)
• hash table 哈希表:通过散列表的形式,降低时间复杂度,增加了空间复杂度,因为大部分哈希表内的格子是空闲的
递归
函数调用自己
- 定义一个basecase 用于判断合适停止,否则会导致无限调用自己
- deffib(n):
- if n == 0:
- return 0
- if n == 1:
- return 1
- return fib(n-1) + fib(n-2)
- fib1= fib(1)
- fib5= fib(5)
- fib25= fib(25)
- linkedlists:递归的数据结构
• 因为每个node都与第二个node相连,所以采用递归的方式处理这种数据结构是合理的,而对应的采用loop会很奇怪
• 当需要查找链表时,由于不知道确定的index,必须一个接一个的查找,所以查找效率不太高
• 但是当发生修改少量节点操作时,比如删除或插入,消耗的时间复杂度和空间复杂度都很小。是线性的。
• # First person's name
• first_item = people.head().get_data()
•
• # Getting the length of the linked list usingiteration
• def length_iterative(ls):
• count = 0
• while notls.is_empty():
• count =count + 1
• ls = ls.tail()
• return count
• people_length = length_iterative(people)
-
Class 类
面向对象的编程:一个合格的工程师需要考虑复杂度问题、选择最优化的解决方案,包括制定详细的计划、一些试验和错误,另外还有经验。
- class Player():
- # The special __init__ function runswhenever a class is instantiated
- # The init function can take arguments, butself is always the first one
- # Self is just a reference to the instanceof the class
- # It's automatically passed in when youinstantiate an instance of the class
- def __init__(self, data_row):
- self.player_name = data_row[0]
- self.position = data_row[1]
- self.age = int(data_row[2])
- self.team = data_row[3]
-
- class Team():
- def __init__(self, team_name):
- self.team_name = team_name
- # Team roster initially empty
- self.roster = []
- # Find the players for the roster inthe data set
- for row in nba:
- if row[3] == self.team_name:
- self.roster.append(Player(row))
- def num_players(self):
- count = 0
- for player in self.roster:
- count += 1
- return count
- # Implement the average_age() instance method
- def average_age(self):
- age = 0
- for player in self.roster:
- age += player.age
- return age/self.num_players()
-
-
- spurs= Team("San Antonio Spurs")
- spurs_num_players= spurs.num_players()
- spurs_avg_age= spurs.average_age()
- classmethod 类方法:在传统的面向对象的编程中,一切(是的,所有)都是一个对象。整数是对象,布尔值也是。尽管Python并不是这种面向对象的,但Python语言中的对象仍然很丰富。例如,math.floor函数实际上只是数学类的一个类方法。类方法作用于整个类,而不是一个特定的实例。我们经常将它们用作实用功能。
-
- 请注意,在起始代码中,我们重写了使用数学类的average_age()方法以及列表理解。这是一些高级的Python代码,但你以前看过。math.fsum方法作用于数学类,获取可迭代的(即列表或类列表)参数,并将列表中的值相加以产生结果。
-
- 另请注意,我们已经开始为您编写一个类方法。出现在它上面的@classmethod行告诉Python解释器该方法是一个类方法。无论何时声明类方法,都需要遵循此模式。
• import math
•
• class Player():
• # Thespecial __init__ function runs whenever a class is instantiated
• # The initfunction can take arguments, but self is always the first one
• # Self isjust a reference to the instance of the class
• # It'sautomatically passed in when you instantiate an instance of the class
• def__init__(self, data_row):
• self.player_name = data_row[0]
• self.position = data_row[1]
• self.age = int(data_row[2])
• self.team = data_row[3]
•
• class Team():
• def__init__(self, team_name):
• self.team_name = team_name
• self.roster = []
• for row in nba:
• if row[3] == self.team_name:
• self.roster.append(Player(row))
•
• defnum_players(self):
• count = 0
• forplayer in self.roster:
• count += 1
• returncount
•
• defaverage_age(self):
• returnmath.fsum([player.age for player in self.roster]) / self.num_players()
•
• @classmethod
• defolder_team(self, team1, team2):
• ifteam1.average_age() > team2.average_age():
• return team1
• else:
• return team2
•
• old_team =Team.older_team(Team("New York Knicks"), Team("MiamiHeat"))
- 继承inheritance父类parent
• 在面向对象的编程中,继承的概念使我们能够在树状层次结构中组织类,其中父类具有传递给其后代的一些特征。当我们定义一个类时,我们指定一个它继承的父类。从类继承意味着父对象的行为也存在于子对象中,但子对象仍然可以定义其自己的附加行为。
• 考虑一个具有关于NBA球员的一般信息的球员类。这会非常有用,因为玩家有很多共同点。但是,我们可能还想为不同的职位添加特定的行为。我们可以定义像Center,Forward或Point Guard这样的类,每个类都具有特定于该位置的行为。这些类将分别指定Player作为其父类。他们都是兄弟姐妹 - 每个人都会从Player类继承相同的行为,同时也具有自己的特殊行为。
• 在Python 3中,每个类都是通用对象类的子类。虽然这种情况在我们没有指定祖先时自动发生,但有时候明确的做法是很好的做法。对于这个任务的其余部分,我们将在代码时指定一个类的对象作为它的父对象。这是一个很好的编程习惯- 如果我们养成了指定类的祖先的习惯,那么当它不是对象时,我们不会忘记指定父类。这只是形成良好习惯的一种方式。
- 重载overloading
• 当一个类继承自一个父类时,它获得了该父类的所有行为。有些时候,我们不想要所有这些行为,或者想为我们的自定义类稍微修改它。我们使用称为重载的技术来实现这一点。
• 重载继承行为涉及将新行为分配给我们的自定义类。为了达到这个目的,我们只是重新定义了我们新课程的方法。
• 我们将改变我们的Player类以支持使用这些运算符的比较:
- >
- <
- ==
- !=
- >=
- <=
• 这些方法默认存在于对象类中,我们使用这些运算符来比较整数,浮点数(小数)和字符串。操作符的工作原因是字符串等类已经专门实现了它们。但是,要理解为什么对象类需要使用这些方法有点困难。围绕这个问题的最好方法就是通过一个例子。
• 让我们考虑加法运算符(+)。对象类已经定义了添加方法。sum()函数是使用这种加法方法定义的,但对象类并不真正知道如何特别添加整数或浮点数。
• 但是,整型和浮点类定义了它们自己的加法方法(从而重载了对象的加法方法),并且sum()函数将正确地将这些值相加。这种体系结构非常强大,因为即使sum()只需要定义一次,我们也可以在多个类上调用它,这会导致正确的行为。这是继承和重载的一个例子。
- classPlayer(object):
- # The special __init__ function runswhenever a class is instantiated
- # The init function can take arguments, butself is always the first one
- #Self is just a reference to the instance of the class
- # It is automatically passed in when youinstantiate an instance of the class
- def __init__(self, data_row):
- self.player_name = data_row[0]
- self.position = data_row[1]
- self.age = int(data_row[2])
- self.team = data_row[3]
- def __lt__(self, other):
- return self.age < other.age
- # Implement the rest of the comparisonoperators here
- def __gt__(self,other):
- return self.age > other.age
- def__le__(self,other):
- return self.age <= other.age
- def __ge__(self,other):
- return self.age >= other.age
- def __eq__(self,other):
- return self.age == other.age
- def __ne__(self,other):
- return self.age != other.age
-
-
- carmelo= Player(nba[17])
- kobe= Player(nba[68])
- result= carmelo != kobe
- 重载没看懂啊~~
- 我们已经看到,我们可以重载运算符来定制类。在最后一个屏幕上,我们可以使用几个比较运算符(>,<,==等)按年龄比较NBA球员。超载行为的能力非常强大,因为许多内置的Python函数使用这些简单的运算符。 如果我们在自定义类上实现它们,我们可以在我们的Player类的实例上使用像min和max这样的函数。 min取一个值列表并返回最小值。 max获取一个值列表并返回最大值。
-
- 我们最初的目标是根据平均年龄比较NBA球队。我们看到我们如何在Player类中重载方法,现在是时候为我们的Team类做同样的事情了。
• import math
•
• class Team(object):
• def__init__(self, team_name):
• self.team_name = team_name
• self.roster = []
• for rowin nba:
• if row[3] == self.team_name:
• self.roster.append(Player(row))
• defnum_players(self):
• count = 0
• forplayer in self.roster:
• count += 1
• returncount
• defaverage_age(self):
• return math.fsum([player.agefor player in self.roster]) / self.num_players()
• def__lt__(self, other):
• returnself.average_age() < other.average_age()
• # Implementthe rest of the comparison operators here
• def__gt__(self,other):
• return self.average_age()> other.average_age()
• def__le__(self,other):
• returnself.average_age() <= other.average_age()
• def__ge__(self,other):
• returnself.average_age() >= other.average_age()
• def__eq__(self,other):
• returnself.average_age() == other.average_age()
• def__ne__(self,other):
• returnself.average_age() != other.average_age()
• # Defineoperators here
•
• jazz = Team("Utah Jazz")
• pistons =Team("Detroit Pistons")
• older_team = max([jazz, pistons])
• 现在我们已经可以获得许多有趣的信息,我们已经实施了比较操作。这是因为Python使用这些比较来实现许多实用功能。 现在我们可以使用这些功能来分析新设置中的数据。 通过重载方法,我们可以访问强大的函数,而无需执行乏味的逻辑。
• import math
•
• class Team(object):
• def__init__(self, team_name):
• self.team_name = team_name
• self.roster = []
• for rowin nba:
• if row[3] == self.team_name:
• self.roster.append(Player(row))
• defnum_players(self):
• count = 0
• forplayer in self.roster:
• count += 1
• returncount
• def average_age(self):
• returnmath.fsum([player.age for player in self.roster]) / self.num_players()
• def__lt__(self, other):
• returnself.average_age() < other.average_age()
• def__gt__(self, other):
• returnself.average_age() > other.average_age()
• def__le__(self, other):
• returnself.average_age() <= other.average_age()
• def__ge__(self, other):
• returnself.average_age() >= other.average_age()
• def__eq__(self, other):
• returnself.average_age() == other.average_age()
• def__ne__(self, other):
• returnself.average_age() != other.average_age()
•
• team_names = ["Boston Celtics","Brooklyn Nets", "New York Knicks", "Philadelphia76ers", "Toronto Raptors",
• "Chicago Bulls","Cleveland Cavaliers", "Detroit Pistons", "IndianaPacers", "Milwaukee Bucks",
• "Atlanta Hawks","Charlotte Hornets", "Miami Heat", "OrlandoMagic", "Washington Wizards",
• "Dallas Mavericks","Houston Rockets", "Memphis Grizzlies", "New OrleansPelicans", "San Antonio Spurs",
• "Denver Nuggets","Minnesota Timberwolves", "Oklahoma City Thunder","Portland Trail Blazers", "Utah Jazz",
• "Golden State Warriors","Los Angeles Clippers", "Los Angeles Lakers", "PhoenixSuns", "Sacramento Kings"]
•
• # Alter this list comprehension
• teams = list([Team(name) for name in team_names])
• oldest_team = max(teams)
• youngest_team = min(teams)
• sorted_teams = sorted(teams)
• 为了解决我们的问题,我们选择了一个将玩家与团队的想法完全分开的实现。通过这样做,我们编写了有组织且合理的代码,这些代码不难追踪。
•
• 通过实施比较运营商,我们能够以非常有效的方式识别最老和最年轻的团队。我们甚至可以用一行代码按年龄排列NBA球队。这是面向对象编程的力量,它突出了明智选择我们实现的重要性。