본문 바로가기
C.W.K.
Stream
Lesson 05 of 05 · published

추론하지 말고 말해 — 어휘를 공유 안 하는 범주

~12 min · ranking, product-design, personalization, limits

Level 0미분류
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

추론이 바닥나는 자리

학습된 키워드 가중치는 한 가지를 잘해. 계속 돌아오는 특정 사건을 잡는 거. 기사를 싫어하면 그 주제를 지명하는 토큰이 음수 가중치를 얻고, 후속편이 가라앉아. 후속편이 문자 그대로 같은 걸 다루고 그 어휘를 공유하니까 되는 거야.

범주 전체는 다른 물건이야. 크리켓 경기 기사랑 축구 이적설은 둘 다 스포츠인데 정확히 겹치는 토큰이 거의 없어. 대회도 다르고, 이름도 다르고, 동사도 다르지. 하나를 아무리 싫어해도 다른 하나는 안 움직여. 둘 사이에 어휘 다리가 없으니까. 독자는 이걸 시스템이 자길 무시하는 걸로 겪어. 계속 싫어함을 누르는데 범주는 계속 도착하니까.

정직한 답은 텍스트 상자야

해법은 더 나은 추론이 아냐. 독자가 말하게 하는 거지. 설정에 치는 음소거 단어 평범한 목록, 결정론적으로 적용. 재미있는 기계 장치에서 후퇴하는 느낌인데 중요한 모든 축에서 엄격히 더 나아. 예시 몇 개가 필요한 대신 즉각적이야. 확률적인 대신 정확하고. 한 자리에서 들여다보고, 고치고, 되돌릴 수 있고. 그리고 돌리는 데 아무 비용도 안 들어.

소리 내어 말하는 게 점수 매기는 쪽이 알아맞히길 바라는 것보다 싸고 정직해. 학습된 절반도 여전히 자기 자리를 벌어. 독자가 이름 붙일 생각도 안 한, 반복되는 사건을 잡거든. 그러니까 두 절반은 경쟁이 아니라 상보야. 예상 못 한 건 추론으로, 이미 아는 건 선언으로.

판정은 카드를 즉시 움직여야 해

제품 규칙 하나가 여기 속해. 같은 신뢰 문제니까. 독자가 싫어함을 누르면 카드가 떠나야 해. 나타나는 모든 자리에서, 그 자리에서 바로. 초기엔 싫어함이 개인화 선반만 구부렸어서, 주제 선반에서 누르면 아무 일도 안 일어나는 걸로 보였어. 신호는 제대로 기록됐고 독자는 그걸 알 방법이 없었지.

버튼을 누르고 나서 새로고침해서 먹혔는지 확인하는 건 투영이 게으른 게 아니라 버그야. 판정이 진짜면 그걸 보여주는 투영이 응답이 나가기 전에 다시 계산돼야 해.

절대 안 걸러지는 선반도 있어

마지막 조각은 경계야. 음소거는 발견 표면에 적용돼. 주제 선반이랑 개인화 피드. 독자가 일부러 챙겨둔 걸 담은 선반엔 절대 아니고. 저장한 기사가 음소거 단어가 들어 있다고 사라지면 안 돼. 그러면 저장 버튼을 못 믿게 되고, 그건 스포츠 헤드라인 하나 새는 것보다 훨씬 나쁜 결과니까.

추론이랑 선언은 다른 문제를 풀고, 둘 중 어느 쪽도 다른 쪽의 대체재가 아냐. 조작 수단이 학습된 것뿐이면 독자가 범주를 표현할 수 없고, 선언된 것뿐이면 전부를 미리 예상해야 해. 실수는 텍스트 상자를 실패 시인으로 취급하는 거야. 사람들이 이미 아는 걸 처리하는 절반인데.

Code

상보적인 절반들인 선언된 단어랑 학습된 가중치, 그리고 경계·python
# The deterministic half of muting: the reader's own list, typed in
# Settings. Learned weights catch a story that keeps coming back; a
# whole CATEGORY shares little exact vocabulary between a cricket
# report and a transfer rumour, so inference alone will always leak.
MUTED_TERMS_KEY = "muted_terms"


def apply_mutes(con, rows, profile=None) -> tuple[list[dict], int]:
    """Drop what the reader has told us they don't want.

    Returns (kept, muted_count) -- the count is returned, never
    swallowed: a shelf that quietly shrinks is a black box.
    """
    if not rows:
        return rows, 0

    declared = set(get_setting(con, MUTED_TERMS_KEY, []))   # said out loud
    profile = mute_profile(con) if profile is None else profile
    common = _common_tokens(rows)                           # DF guard

    kept = []
    for row in rows:
        toks = tokens(row)
        if declared & toks:
            continue                       # exact, instant, inspectable
        if mute_score(row, profile, skip=common) <= MUTE_THRESHOLD:
            continue                       # learned, for what wasn't named
        kept.append(row)
    return kept, len(rows) - len(kept)


# The boundary: discovery surfaces are filtered, kept ones never are.
# A saved article vanishing because a muted term appears in it would
# make the save button untrustworthy -- a far worse outcome than a
# stray headline.
MUTABLE_SHELF_KINDS = {"topic", "foryou"}      # not saved, not queued

External links

Exercise

네가 쓰는 개인화 기능을 하나 골라서, 절대 보기 싫은 범주 하나를 표현해봐. 제품이 그걸 말할 방법을 주는지, 아니면 개별 항목에 반응할 방법만 주는지 적어봐. 그리고 예시로 그 범주를 가르치려면 개별 반응이 몇 번 필요할지, 그리고 항목들이 수렴할 만큼 표면을 공유하기는 하는지 세봐.
Hint
추론에 저항하는 범주는 단어가 아니라 개념으로 정의된 것들이야. 스포츠, 연예 뉴스, 특정 감정이나 어조에 관한 것들. 쉽게 넘어오는 범주는 고유명사고. 제품이 항목별 피드백만 준다면, 네가 싫어하는 모든 범주가 고유명사라고 암묵적으로 가정하는 거야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.