После долгой борьбы я завершил проект Наследственность «Введение в искусственный интеллект CS50». Однако мне кажется, что мое решение было не самым достойным.
Итак, для этой конкретной функции, над которой я работал, цель состоит в том, чтобы вычислить совместную вероятность того, что произойдет множество событий, например, у одного человека есть 2 гена, но нет признака, а у другого человека есть 1 ген и проявляется признак.
Моя завершенная функция ниже расскажет вам, как она работает. Обычно, если у человека нет в списке родителей, я просто использую PROBS
словарь, чтобы получить вероятность, а если у человека есть родители, я использую информацию родителей, чтобы найти информацию о ребенке.
Пример people
было бы это:
{
'Harry': {'name': 'Harry', 'mother': 'Lily', 'father': 'James', 'trait': None},
'James': {'name': 'James', 'mother': None, 'father': None, 'trait': True},
'Lily': {'name': 'Lily', 'mother': None, 'father': None, 'trait': False}
}
И PROBS
выглядит так:
PROBS = {
# Unconditional probabilities for having gene
"gene": {
2: 0.01,
1: 0.03,
0: 0.96
},
"trait": {
# Probability of trait given two copies of gene
2: {
True: 0.65,
False: 0.35
},
# Probability of trait given one copy of gene
1: {
True: 0.56,
False: 0.44
},
# Probability of trait given no gene
0: {
True: 0.01,
False: 0.99
}
},
# Mutation probability
"mutation": 0.01
}
И one_gene
, two_genes
, и have_trait
представляют собой просто наборы, содержащие строки имен людей.
Мой вопрос: в моем решении используется CHILD_PROB
словарь, который я вычислил. Есть ли у меня способ динамически вычислить вероятность гена ребенка без этого словаря, просто выполняя вычисления с вероятностью мутации и информацией о родительском гене? Если да, будет ли оно более или менее элегантным, чем мое текущее решение?
См. Эту ссылку для получения дополнительной информации о проекте: https://cs50.harvard.edu/ai/2020/projects/2/heredity/
def joint_probability(people, one_gene, two_genes, have_trait):
"""
Compute and return a joint probability.
The probability returned should be the probability that
* everyone in set `one_gene` has one copy of the gene, and
* everyone in set `two_genes` has two copies of the gene, and
* everyone not in `one_gene` or `two_gene` does not have the gene, and
* everyone in set `have_trait` has the trait, and
* everyone not in set` have_trait` does not have the trait.
"""
return_prob = 1
mut = PROBS["mutation"]
# Probability for child given parent tuple
CHILD_PROB = {
(2, 2): (mut**2, 2*mut*(1-mut), (1-mut)**2),
(2, 1): (0.5*mut, 0.5, (1-mut)*0.5),
(2, 0): (mut*(1-mut), (1-mut)**2 + mut**2, (1-mut)*mut),
(1, 1): (0.25, 0.5, 0.25),
(1, 0): (0.5*(1-mut), 0.5, 0.5*mut),
(0, 0): ((1-mut)**2, 2*mut*(1-mut), mut**2)
}
for person in people.keys():
# Figure out how many genes person should have
if person in one_gene:
genum = 1
elif person in two_genes:
genum = 2
else:
genum = 0
if people[person]["father"] == None:
# Use PROBS if person's parents aren't listed
return_prob *= PROBS["gene"][genum]
else:
parent_genes = {"mother": 0, "father": 0}
# Get parents' genes
for parent_str in parent_genes.keys():
parent = people[person][parent_str]
if parent is not None:
parent_genes[parent_str] = 1 if parent in one_gene else 2 if parent in two_genes else 0
# Try both tuple orders
try:
return_prob *= CHILD_PROB[(parent_genes["mother"], parent_genes["father"])][genum]
except KeyError:
return_prob *= CHILD_PROB[(parent_genes["father"], parent_genes["mother"])][genum]
# Get person's trait probability
if person in have_trait:
return_prob *= PROBS["trait"][genum][True]
else:
return_prob *= PROBS["trait"][genum][False]
return return_prob
```