tfidf = термин частота (tf) * обратная частота документа (idf)
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(documents)
print(vectorizer.get_feature_names())
print (X.toarray())
print ("---")
t = TfidfTransformer(use_idf=True, norm=None, smooth_idf=False)
a = t.fit_transform(X)
print (a.toarray())
print ("---")
print (t.idf_)
Выход:
[ 116] idf (the) низкий, но tf (the, doc1) = 2 высокий, что толкает его на другие слова.
Из приведенного выше примера кода:
IDF (без норм, без сглаживания IDF) == the == 1
Однако tf (the, doc1) = 2 и tf (is, doc1) = 1, что увеличивает значение tfidf для tfidf (the, doc1).
аналогично idf (car) = 2.09861229, но tf (car, doc1) = 1, => tfidf (car, doc1) = 2.09861229, что очень близко к tfidf (the, doc1). Сглаживание IDF еще больше уменьшает разрыв.
На большом корпусе различия становятся более заметными.
Попробуйте запустить свой код, отключив сглаживание и не нормализуя, чтобы увидеть влияние на небольшой корпус.
tfidf_transformer = TfidfVectorizer (smooth_idf = False, use_idf = True, norm = None)
blockquote>
Есть несколько способов сделать это. Во-первых, вы можете установить два отношения assign_to
/ has_one
:
things
- bar:int
- foo_id:int
- goo_id:int
whazits
- content:string
- value:int
class Thing < ActiveRecord::Base
belongs_to :foo, :class_name => "whazit"
belongs_to :goo, :class_name => "whazit"
end
class Whazit < ActiveRecord::Base
has_one :foo_owner, class_name => "thing", foreign_key => "foo_id"
has_one :goo_owner, class_name => "thing", foreign_key => "goo_id"
# Perhaps some before save logic to make sure that either foo_owner
# or goo_owner are non-nil, but not both.
end
Еще один вариант, который немного чище, но также более труден при работе с плагинами и т. Д. наследование одной таблицы. В этом случае у вас есть два класса, Foo и Goo, но они оба хранятся в таблице whazits со столбцом типа, который их различает.
things
- bar:int
whazits
- content:string
- value:int
- thing_id:int
- type:string
class Thing < ActiveRecord::Base
belongs_to :foo
belongs_to :goo
end
class Whazit < ActiveRecord::Base
# .. whatever methods they have in common ..
end
class Foo < Whazit
has_one :thing
end
class Goo < Whazit
has_one :thing
end
В обоих случаях вы можете делать такие вещи, как @ thing.foo
и @ thing.goo
. С первым методом вам нужно будет сделать что-то вроде:
@thing.foo = Whazit.new
, тогда как со вторым методом вы можете сделать что-то вроде:
@thing.foo = Foo.new
STI имеет свой собственный набор проблем, особенно если вы используете старые плагины и драгоценные камни. Обычно это проблема с кодом, вызывающим @object. класс
, когда они действительно хотят @ object.base_class
. Это достаточно легко исправить при необходимости.
Ваше простое решение с добавлением «имени» не должно быть уродливым:
class Thing < ActiveRecord::Base
has_one :foo, :class_name => "whazit", :conditions => { :name => "foo" }
has_one :goo, :class_name => "whazit", :conditions => { :name => "goo" }
end
Фактически, это очень похоже на то, как работает STI, за исключением того, что вам не нужен отдельный класс.
Единственное, на что вам нужно обратить внимание, это установить это имя, когда вы связываете whazit. Это может быть очень просто:
def foo=(assoc)
assos.name = 'foo'
super(assoc)
end